---
# System prepended metadata

title: 函式介面 - Consumer、Function、Predicate 與 Supplier
tags: [Java]

---

---
tags: Java
---

# 函式介面 - Consumer、Function、Predicate 與 Supplier

## 前言

補充關於 Consumer、Function、Predicate 與 Supplier 的一些資訊。

## 目錄

* [前言](#前言)
* [目錄](#目錄)
* [介紹/基本概念](#介紹/基本概念)
  * [Consumer](#Consumer)
  * [Supplier](#Supplier)
  * [Predicate](#Predicate)
  * [Function](#Function)
* [實作過程](#實作過程)
  * [Consumer 的實作過程](#Consumer-的實作過程)
  * [Supplier 的實作過程](#Supplier-的實作過程)
  * [Predicate 的實作過程](#Predicate-的實作過程)
  * [Function 的實作過程](#Function-的實作過程)
* [參考資料](#參考資料)

## 介紹/基本概念

### Consumer

Consumer Interface 是一個消費型的介面，裡面長這樣，有兩個方法，一個 accept 和默認 andThen 方法，通過傳入參數，然後輸出值，大概是這樣的方法，常常會搭配 Stream 一起使用。

```java=
@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}
```

### Supplier

Supplier 是個供給型的介面，就像是一個容器，負責儲存資料和值。

```java=
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
```

### Predicate

Predicate 是一個判斷 bool 的介面。

```java=
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}
```

### Function

Function 是功能型介面，它的作用是將輸入資料轉出成另一種形式的輸出資料。

```java=
@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
```

## 實作過程

### Consumer 的實作過程

#### 1. 使用 Consumer 介面實現方法

```java=
public class ConsumerDemo1 {
    public static void main(String[] args) {
        Consumer<String> eatHamburger = new Consumer<String>() {

            @Override
            public void accept(String customer) {
                System.out.println(customer +" eats a hamburger");
            }
        };
        Stream<String> customers = Stream.of("Eric", "Tony", "Erica", "Daniel", "Sophia");
        customers.forEach(eatHamburger);
    }
}
```

![1](https://i.imgur.com/1u2R9Oi.png)

#### 2. 使用 lambda 實現 Consumer

```java=
public class ConsumerDemo2 {
    public static void main(String[] args) {
        Stream<String> customers = Stream.of("Eric", "Tony", "Erica", "Daniel", "Sophia");
        Consumer<String> eatHamburger = (customer) -> System.out.println(customer +" eats a hamburger");
        customers.forEach(eatHamburger);
    }
}
```

![2](https://i.imgur.com/G9mwGLr.png)

#### 3. 使用方法引用 Consumer

```java=
public class ConsumerDemo3 {
    public static void main(String[] args) {
        Stream<String> customers = Stream.of("Eric", "Tony", "Erica", "Daniel", "Sophia");
        Consumer<String> eatHamburger = EatHamburger::eat;
        customers.forEach(eatHamburger);
    }
}
```

```java=
public class EatHamburger {
    public static void eat(String customer) {
        System.out.println(customer +" eats a hamburger");
    }
}
```

![3](https://i.imgur.com/0GbCtVw.png)

以上方式都會執行 Consumer 方法的印出方式，讓 stream 內的每個元素執行 Consumer 內的方法。

#### Consumer 舉例使用

```java=
// forEach 就是使用 Consumer 介面的
void forEach(Consumer<? super T> action);
```

### Supplier 的實作過程

#### 1. 使用 Supplier 介面實現方法

```java=
public class SupplierDemo1 {
    public static void main(String[] args) {
        Supplier<Double> randomLuckyNumber = new Supplier<Double>() {
            @Override
            public Double get() {
                return new Random().nextDouble();
            }
        };
        System.out.println(randomLuckyNumber.get());
    }
}
```

![4](https://i.imgur.com/EW9deOd.png)

#### 2. 使用 lambda 實現 Supplier

```java=
public class SupplierDemo2 {
    public static void main(String[] args) {
        Supplier<Double> randomLuckyNumber = () -> new Random().nextDouble();
        System.out.println(randomLuckyNumber.get());
    }
}
```

![5](https://i.imgur.com/ON8Siat.png)

#### 3. 使用方法引用 Supplier

```java=
public class SupplierDemo3 {
    public static void main(String[] args) {
        Supplier<Double> randomLuckyNumber = Math::random;
        System.out.println(randomLuckyNumber.get());
    }
}
```

![6](https://i.imgur.com/SrUPPju.png)

以上的 Supplier 都可以得到一個隨機幸運數。

#### 4. 搭配 Stream 使用 Supplier

```java=
public class SupplierDemo4 {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(3,7,9);

        Optional<Integer> first = stream.filter(i -> i > 11)
                .findFirst();

        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(10);
            }
        };
        
        // orElseGet 如果 first 存在此數，就返回這個數字，如果不存在，就返回 supplier 的值
        System.out.println(first.orElseGet(supplier));
    }
}
```

![7](https://i.imgur.com/sAVHKXp.png)

#### Supplier 舉例使用

```java=
// collect 是使用 Supplier 的
<R> R collect(Supplier<R> supplier,
              BiConsumer<R, ? super T> accumulator,
              BiConsumer<R, R> combiner);
```

### Predicate 的實作過程

#### 1. 使用 Predicate 介面實現方法

```java=
public class PredicateDemo1 {
    public static void main(String[] args) {
        Predicate<Integer> integerBiggerThan5 = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

        System.out.println(integerBiggerThan5.test(6));
    }
```

![8](https://i.imgur.com/8ebTuEl.png)

#### 2. 使用 lambda 實現 Predicate

```java=
public class PredicateDemo2 {
    public static void main(String[] args) {
        Predicate<Integer> integerBiggerThan5 = (t) -> t > 5;
        System.out.println(integerBiggerThan5.test(1));
    }
}
```

![9](https://i.imgur.com/LQMhX1l.png)

以上都可以使用 Predicate 得到 Boolean。

#### 3. 搭配 Stream 使用 Predicate

```java=
public class PredicateDemo3 {
    public static void main(String[] args) {
        Predicate<Integer> numberBiggerThan5 = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };


        Stream<Integer> numbers = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
        List<Integer> numbersBiggerThan5 = numbers.filter(numberBiggerThan5).collect(Collectors.toList());
        numbersBiggerThan5.forEach(System.out::println);
    }

}
```

可以得到所有大於 5 的數字。

![10](https://i.imgur.com/QNjhndb.png)

#### Predicate 舉例使用

```java=
// filter 方法是使用 Predicate 的
Stream<T> filter(Predicate<? super T> predicate);
```

### Function 的實作過程

#### 1. 使用 Function 介面實現方法

```java=
public class FunctionDemo1 {
    public static void main(String[] args) {
        Function<String, Integer> lengthOfName = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        };

        Stream<String> names = Stream.of("Eric", "Allen", "Johny");
        Stream<Integer> lengthOfNames = names.map(lengthOfName);
        lengthOfNames.forEach(System.out::println);
    }
}
```

![11](https://i.imgur.com/9hfiKET.png)

印出 Stream 字串長度。

![10](https://i.imgur.com/QNjhndb.png)

#### Function 舉例使用

```java=
// map 方法是使用 Function 的
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
```

## 參考資料

[面试又挂了，你理解了 Java 8 的 Consumer、Supplier、Predicate和Function吗？](https://cloud.tencent.com/developer/article/1488128)
