Predicate接口
Predicate接口介紹
??Predicate是函數式接口,可以使用Lambda表達式作為參數。Java 8為集合Collection新增了removeIf(Predicate filter)
方法,可以批量刪除符合filter條件的所有元素。
Predicate接口使用范例
測試Collection的removeIf()
方法。
示例1
1)運行類:
public class DemoApplication {
public static void main(String[] args) {
// 創建集合
Collection collection = new HashSet();
// 添加元素
collection.add("book01");
collection.add("book02");
collection.add("book03");
collection.add("b05");
collection.add("b06");
Collection collectionNew = new HashSet();
// 使用Lambda表達式遍歷傳入新的集合
collection.forEach(str -> collectionNew.add(str));
System.out.println("collectionNew: " + collectionNew);
// 使用Lambda表達式進行過濾(目標類型是Predicate)
collection.removeIf(filter -> ((String)filter).length() < 5);
// 使用Lambda表達式遍歷打印
collection.forEach(str -> System.out.println(str));
}
}
2)運行結果:
collectionNew: [book02, book01, b05, book03, b06]
book02
book01
book03
??從上述結果中,我們可以看到調用Collection集合的removeIf()
方法,可以批量過濾符合條件長度小于5的集合元素,程序是傳入一個Lambda表達式進行過濾:collection.removeIf(filter -> ((String)filter).length() < 5);
。
示例2
使用Predicate接口的boolean test(T t);
方法
1)創建工具類:
import java.util.Collection;
import java.util.function.Predicate;
/**
* @author andya
* @create 2020-03-24 14:08
*/
public class PredicateUtil {
public static int countCollectionElement(Collection collection, Predicate predicate){
int total = 0;
for (Object object : collection) {
//通過Predicate的test()方法判斷對象是否滿足過濾條件
if (predicate.test(object)) {
total ++;
}
}
return total;
}
}
2)運行類:
public class DemoApplication {
public static void main(String[] args) {
// 創建集合
Collection collection = new HashSet();
// 添加元素
collection.add("book_java編程思想");
collection.add("book_c++核心技術");
collection.add("book_java核心技術");
collection.add("book_計算機網絡");
collection.add("book01");
collection.add("book02");
Collection collectionNew = new HashSet();
// 使用Lambda表達式遍歷傳入新的集合
collection.forEach(str -> collectionNew.add(str));
System.out.println("collectionNew: " + collectionNew);
System.out.println("包含java關鍵字的個數:" +
PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).contains("java")));
System.out.println("長度小于7的個數:" +
PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).length() < 7));
System.out.println("以book_為前綴的個數:" +
PredicateUtil.countCollectionElement(collection, ele -> ((String)ele).startsWith("book_")));
}
}
3)運行結果:
collectionNew: [book02, book01, book_java編程思想, book_java核心技術, book_計算機網絡, book_c++核心技術]
包含java關鍵字的個數:2
長度小于7的個數:2
以book_為前綴的個數:4
??定義了一個countCollectionElement()
方法,使用Predicate動態傳參,判斷每個集合元素是否符合過濾條件。
Stream流式接口
Stream流式接口介紹
??Java 8新特性中還增加了流式處理,如Stream,IntStream,DoubleStream,LongStream等API。每個流式API還提供了對應的Builder,如Stream.Builder、IntStream.Builder、DoubleStream.Builder、LongStream.Builder。
Stream使用步驟
- 通過Stream等API的
builder()
類方法去創建Stream對應的Builder類; - 調用Builder的
add()
方法向流中添加多個元素; - 調用Builder的
build()
方法獲取對應的Stream; - 調用Stream聚集方法;
Stream使用示例
public class DemoApplication {
public static void main(String[] args) {
//通過xxxStream的builder()方法去創建Builder
IntStream intStream = IntStream.builder()
.add(1)
.add(-2)
.add(3)
.add(10)
.build();
// 聚集方法(每次只能使用其中一條去執行,其他代碼需注釋,否則會報錯)
System.out.println("intStream的元素最大值是: " + intStream.max().getAsInt());
System.out.println("intStream的元素最小值是: " + intStream.min().getAsInt());
System.out.println("intStream的元素平均值是: " + intStream.average());
System.out.println("intStream的元素總和是: " + intStream.sum());
System.out.println("intStream的元素個數是: " + intStream.count());
System.out.println("intStream是否包含任何元素平方大于10: "
+ intStream.anyMatch(ele -> ele * ele > 10));
System.out.println("intStream的所有元素立方是否大于10: "
+ intStream.allMatch(ele -> ele * ele * ele > 10));
// 每個元素都加1后映射成新的Stream
IntStream intStreamNew = intStream.map(ele -> ele + 1);
intStreamNew.forEach(ele -> System.out.println(ele));
}
}
運行結果:將上述聚集方法所有執行結果放在一個里面進行展示,其實只能執行一條;
intStream的元素最大值是: 10
intStream的元素最小值是: -2
intStream的元素平均值是: OptionalDouble[3.0]
intStream的元素總和是: 12
intStream的元素個數是: 4
intStream是否包含任何元素平方大于10: true
intStream的所有元素立方是否大于10: false
2
-1
4
11
在上述示例中存在兩種聚集方法:“中間方法”和“末端方法”。
-
中間方法:中間操作允許流保持打開狀態,并允許直接調用后續方法,如
map()
方法,返回值為另一個流; -
末端方法:末端方法是對流進行的最終操作,如
sum()
方法執行后,流就不可用,如果再用會報錯Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
Stream的常用方法
中間方法
-
filter(Predicate predicate)
:過濾Stream中不符合predicate過濾條件的元素。 -
mapToXxx(ToXxxFunction mapper)
:使用ToXxxFunction對流中的元素執行一對一的轉換,方法返回的是新流中包含了ToXxxFunction轉換生成的所有元素。 -
peek(Consumer action)
:依次操作每個元素,返回的流與原有流包含相同的元素,用于調試。 -
distinct()
:用于排序流中所有重復的元素,有狀態的方法; -
sorted()
:用于保證流中的元素在后續的訪問中處于有序狀態,也是有狀態的方法。 -
limit(long maxSize)
:用于保證對該流的后續訪問中最大允許訪問的元素個數,是一個有狀態的、短路方法。
末端方法
-
forEach(Consumer action)
:遍歷流中所有元素,執行action。 -
toArray()
:將流中所有元素轉換成一個數組。 -
reduce()
:用于某個操作合并流中元素。 -
min()
:返回流中元素的最小值。 -
max()
:返回流中元素的最大值。 -
sum()
:返回流中元素的總和。 -
count()
:返回流中所有元素的數量。 -
anyMatch(Predicate predicate)
:判斷流中是否至少包含一個元素符合predicate過濾條件。 -
allMatch(Predicate predicate)
:判斷流中是否所有元素符合predicate過濾條件。 -
noneMatch(Predicate predicate)
:判斷流中是否所有元素都不符合predicate過濾條件。 -
findFirst()
:返回流中的第一個元素。 -
findAny()
:返回流中的任意一個元素。
Collection中的stream()方法
public class DemoApplication {
public static void main(String[] args) {
// 創建集合
Collection collection = new HashSet();
// 添加元素
collection.add("book_java編程思想");
collection.add("book_c++核心技術");
collection.add("book_java核心技術");
collection.add("book_計算機網絡");
collection.add("book01");
collection.add("book02");
collection.forEach(ele -> System.out.println(ele));
System.out.println("-------------------------------------");
System.out.println("包含java關鍵字的個數:"
+ collection.stream().filter(ele -> ((String)ele).contains("java")).count());
System.out.println("長度小于7的個數:"
+ collection.stream().filter(ele -> ((String)ele).length() < 7).count());
System.out.println("以book_為前綴的個數:"
+ collection.stream().filter(ele -> ((String)ele).startsWith("book_")).count());
System.out.println("-------------------------------------");
//先調用Collection的stream()方法將集合轉化為Stream;
//再調用Stream的mapToInt()方法獲取Stream對象的IntStream對象;
//最后調用forEach()方法遍歷IntStream中的元素。
Collection collectionLength = new ArrayList();
collection.stream().mapToInt(ele -> ((String)ele).length())
.forEach(ele -> ((ArrayList) collectionLength).add(ele));
//等價于collectionLength.forEach(ele -> System.out.println(ele));
collectionLength.forEach(System.out::println);
}
}
運行結果
book02
book01
book_java編程思想
book_java核心技術
book_計算機網絡
book_c++核心技術
-------------------------------------
包含java關鍵字的個數:2
長度小于7的個數:2
以book_為前綴的個數:4
-------------------------------------
6
6
13
13
10
12
??通過collection.stream().filter(Predicate<? super T> predicate).count()
這種方式就可以替換文章中前面創建的PredicateUtil的方法。
??除了直接使用Stream流式接口去處理Collection集合的元素,我們還可以通過Collection接口的stream()
方法返回集合對應的流。
步驟如下:
- 先調用Collection的
stream()
方法將集合轉化為Stream; - 再調用Stream的
mapToInt()
方法獲取Stream對象的IntStream對象; - 最后調用
forEach()
方法遍歷IntStream中的元素。
參考書籍《瘋狂Java》