- 2020部落格位址彙總
- 2019年部落格彙總
轉載:https://www.cnblogs.com/SIHAIloveYAN/p/11288064.html
今天我們還講講Consumer、Supplier、Predicate、Function這幾個接口的用法,在 Java8 的用法當中,這幾個接口雖然沒有明目張膽的使用,但是,卻是潤物細無聲的。為什麼這麼說呢?
這幾個接口都在
java.util.function
包下的,分别是Consumer(消費型)、supplier(供給型)、predicate(謂詞型)、function(功能性),相信有了後面的解釋,你應該非常清楚這個接口的功能了。
那麼,下面,我們從具體的應用場景來講講這個接口的用法!
1 Consumer接口
從字面意思上我們就可以看得出啦,
consumer接口
就是一個消費型的接口,通過傳入參數,然後輸出值,就是這麼簡單,Java8 的一些方法看起來很抽象,其實,隻要你了解了就覺得很好用,并且非常的簡單。
我們下面就先看一個例子,然後再來分析這個接口。
1.1 Consumer執行個體
/**
* consumer接口測試
*/
@Test
public void test_Consumer() {
//① 使用consumer接口實作方法
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
stream.forEach(consumer);
System.out.println("********************");
//② 使用lambda表達式,forEach方法需要的就是一個Consumer接口
stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表達式傳回的就是一個Consumer接口
stream.forEach(consumer1);
//更直接的方式
//stream.forEach((s) -> System.out.println(s));
System.out.println("********************");
//③ 使用方法引用,方法引用也是一個consumer
stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
Consumer consumer2 = System.out::println;
stream.forEach(consumer);
//更直接的方式
//stream.forEach(System.out::println);
}
輸出結果
1.2 執行個體分析
①
consumer
接口分析
在代碼①中,我們直接建立
Consumer
接口,并且實作了一個名為
accept
的方法,這個方法就是這個接口的關鍵了。
我們看一下
accept
方法;這個方法傳入一個參數,不傳回值。當我們發現
forEach
需要一個
Consumer
類型的參數的時候,傳入之後,就可以輸出對應的值了。
② lambda 表達式作為 consumer
Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表達式傳回的就是一個Consumer接口
在上面的代碼中,我們使用下面的
lambda
表達式作為
Consumer
。仔細的看一下你會發現,
lambda
表達式傳回值就是一個
Consumer
;是以,你也就能夠了解為什麼
forEach
方法可以使用 lamdda 表達式作為參數了吧。
③ 方法引用作為 consumer
Consumer consumer2 = System.out::println;
在上面的代碼中,我們用了一個方法引用的方式作為一個 Consumer ,同時也可以傳給
forEach
方法。
1.3 其他 Consumer 接口
除了上面使用的 Consumer 接口,還可以使用下面這些 Consumer 接口。
IntConsumer、DoubleConsumer、LongConsumer、BiConsumer
,使用方法和上面一樣。
1.4 Consumer 總結
看完上面的執行個體我們可以總結為幾點。
① Consumer是一個接口,并且隻要實作一個
accept
方法,就可以作為一個“消費者”輸出資訊。
② 其實,lambda 表達式、方法引用的傳回值都是 Consumer 類型,是以,他們能夠作為
forEach
方法的參數,并且輸出一個值。
2 Supplier 接口
Supplier 接口是一個供給型的接口,其實,說白了就是一個容器,可以用來存儲資料,然後可以供其他方法使用的這麼一個接口,是不是很明白了,如果還是不明白,看看下面的例子,一定徹底搞懂!
2.1 Supplier執行個體
**
* Supplier接口測試,supplier相當一個容器或者變量,可以存儲值
*/
@Test
public void test_Supplier() {
//① 使用Supplier接口實作方法,隻有一個get方法,無參數,傳回一個值
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
//傳回一個随機值
return new Random().nextInt();
}
};
System.out.println(supplier.get());
System.out.println("********************");
//② 使用lambda表達式,
supplier = () -> new Random().nextInt();
System.out.println(supplier.get());
System.out.println("********************");
//③ 使用方法引用
Supplier<Double> supplier2 = Math::random;
System.out.println(supplier2.get());
}
輸出結果
2.2 執行個體分析
① Supplier接口分析
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
//傳回一個随機值
return new Random().nextInt();
}
};
看一下這段代碼,我們通過建立一個 Supplier 對象,實作了一個
get
方法,這個方法無參數,傳回一個值;是以,每次使用這個接口的時候都會傳回一個值,并且儲存在這個接口中,是以說是一個容器。
② lambda表達式作為 Supplier
//② 使用lambda表達式,
supplier = () -> new Random().nextInt();
System.out.println(supplier.get());
System.out.println("********************");
上面的這段代碼,我們使用 lambda 表達式傳回一個 Supplier類型的接口,然後,我們調用
get
方法就可以擷取這個值了。
③ 方法引用作為 Supplier
//③ 使用方法引用
Supplier<Double> supplier2 = Math::random;
System.out.println(supplier2.get());
方法引用也是傳回一個Supplier類型的接口。
2.3 Supplier 執行個體2
我們看完第一個執行個體之後,我們應該有一個了解了,下面再看一個。
/**
* Supplier接口測試2,使用需要Supplier的接口方法
*/
@Test
public void test_Supplier2() {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
//傳回一個optional對象
Optional<Integer> first = stream.filter(i -> i > 4)
.findFirst();
//optional對象有需要Supplier接口的方法
//orElse,如果first中存在數,就傳回這個數,如果不存在,就放回傳入的數
System.out.println(first.orElse(1));
System.out.println(first.orElse(7));
System.out.println("********************");
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
//傳回一個随機值
return new Random().nextInt();
}
};
//orElseGet,如果first中存在數,就傳回這個數,如果不存在,就傳回supplier傳回的值
System.out.println(first.orElseGet(supplier));
}
輸出結果
代碼分析
Optional<Integer> first = stream.filter(i -> i > 4)
.findFirst();
使用這個方法擷取到一個 Optional 對象,然後,在 Optional 對象中有 orElse 方法 和 orElseGet 是需要一個 Supplier 接口的。
//optional對象有需要Supplier接口的方法
//orElse,如果first中存在數,就傳回這個數,如果不存在,就放回傳入的數
System.out.println(first.orElse(1));
System.out.println(first.orElse(7));
System.out.println("********************");
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
//傳回一個随機值
return new Random().nextInt();
}
};
//orElseGet,如果first中存在數,就傳回這個數,如果不存在,就傳回supplier傳回的值
System.out.println(first.orElseGet(supplier));
- orElse:如果first中存在數,就傳回這個數,如果不存在,就放回傳入的數
- orElseGet:如果first中存在數,就傳回這個數,如果不存在,就傳回supplier傳回的值
2.4 其他 Supplier 接口
除了上面使用的 Supplier 接口,還可以使用下面這些 Supplier 接口。
IntSupplier 、DoubleSupplier 、LongSupplier 、BooleanSupplier
,使用方法和上面一樣。
2.5 Supplier 總結
① Supplier 接口可以了解為一個容器,用于裝資料的。
② Supplier 接口有一個
get
方法,可以傳回值。
3 Predicate 接口
Predicate 接口是一個謂詞型接口,其實,這個就是一個類似于 bool 類型的判斷的接口,後面看看就明白了。
3.1 Predicate 執行個體
/**
* Predicate謂詞測試,謂詞其實就是一個判斷的作用類似bool的作用
*/
@Test
public void test_Predicate() {
//① 使用Predicate接口實作方法,隻有一個test方法,傳入一個參數,傳回一個bool值
Predicate<Integer> predicate = new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
if(integer > 5){
return true;
}
return false;
}
};
System.out.println(predicate.test(6));
System.out.println("********************");
//② 使用lambda表達式,
predicate = (t) -> t > 5;
System.out.println(predicate.test(1));
System.out.println("********************");
}
輸出結果
3.2 執行個體分析
① Predicate 接口分析
//① 使用Predicate接口實作方法,隻有一個test方法,傳入一個參數,傳回一個bool值
Predicate<Integer> predicate = new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
if(integer > 5){
return true;
}
return false;
}
};
這段代碼中,建立了一個
Predicate
接口對象,其中,實作類
test
方法,需要傳入一個參數,并且傳回一個
bool
值,是以這個接口作用就是判斷!
System.out.println(predicate.test(6));
再看,調用 test 方法,傳入一個值,就會傳回一個 bool 值。
② 使用lambda表達式作為 predicate
//② 使用lambda表達式,
predicate = (t) -> t > 5;
System.out.println(predicate.test(1));
System.out.println("********************");
lambda 表達式傳回一個
Predicate
接口,然後調用
test
方法!
3.3 Predicate 接口執行個體2
/**
* Predicate謂詞測試,Predicate作為接口使用
*/
@Test
public void test_Predicate2() {
//① 将Predicate作為filter接口,Predicate起到一個判斷的作用
Predicate<Integer> predicate = new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
if(integer > 5){
return true;
}
return false;
}
};
Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("********************");
}
輸出結果
這段代碼,首先建立一個 Predicate 對象,然後實作
test
方法,在 test 方法中做一個判斷:如果傳入的參數大于 5 ,就傳回 true,否則傳回 false;
Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
list.forEach(System.out::println);
這段代碼調用
Stream
的
filter
方法,
filter
方法需要的參數就是 Predicate 接口,是以在這裡隻要大于 5 的資料就會輸出。
3.4 Predicate 接口總結
① Predicate 是一個謂詞型接口,其實隻是起到一個判斷作用。
② Predicate 通過實作一個
test
方法做判斷。
4 Function 接口
Function 接口是一個功能型接口,它的一個作用就是轉換作用,将輸入資料轉換成另一種形式的輸出資料。
4.1 Function 接口執行個體
/**
* Function測試,function的作用是轉換,将一個值轉為另外一個值
*/
@Test
public void test_Function() {
//① 使用map方法,泛型的第一個參數是轉換前的類型,第二個是轉化後的類型
Function<String, Integer> function = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();//擷取每個字元串的長度,并且傳回
}
};
Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
Stream<Integer> stream1 = stream.map(function);
stream1.forEach(System.out::println);
System.out.println("********************");
}
輸出結果
4.2 代碼分析
① Function 接口分析
//① 使用map方法,泛型的第一個參數是轉換前的類型,第二個是轉化後的類型
Function<String, Integer> function = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.length();//擷取每個字元串的長度,并且傳回
}
};
這段代碼建立了一個
Function
接口對象,實作了一個
apply
方法,這個方法有一個輸入參數和一個輸出參數。其中,泛型的第一個參數是轉換前的類型,第二個是轉化後的類型。
在上面的代碼中,就是擷取字元串的長度,然後将每個字元串的長度作為傳回值傳回。
② 重要應用 map 方法
Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
Stream<Integer> stream1 = stream.map(function);
stream1.forEach(System.out::println);
在
Function
接口的重要應用不得不說
Stream
類的
map
方法了,
map
方法傳入一個
Function
接口,傳回一個轉換後的
Stream
類。
4.3 其他 Function 接口
除了上面使用的 Function 接口,還可以使用下面這些 Function 接口。
IntFunction 、DoubleFunction 、LongFunction 、ToIntFunction 、ToDoubleFunction 、DoubleToIntFunction 等等,使用方法和上面一樣。
4.4 Function 接口總結
① Function 接口是一個功能型接口,是一個轉換資料的作用。
② Function 接口實作
apply
方法來做轉換。
5 總結
通過前面的介紹,已經對
Consumer、Supplier、Predicate、Function
這幾個接口有詳細的了解了,其實,這幾個接口并不是很難,隻是有點抽象,多加了解會發現很簡單,并且特别好用!