我們一起聊聊 Java Steam 常用 API
現(xiàn)在 Java 17 和 Java 11 基本上可以和 Java8 平分 JDK 裝機(jī)比例。下面是我常用的一些 Strem API 操作。除了分組、轉(zhuǎn)換、排序,如果大家還有更多常用的 API 可以一起留言交流。
分組
List 默認(rèn)分組過后是 Map<Key, List>
List<StreamItem> streamList = Stream.of(
new StreamItem(1, "k1"),
new StreamItem(2, "k1"),
new StreamItem(3, "k2"),
new StreamItem(4, "k2")).collect(Collectors.toList());
System.out.println(streamList);
//1.1分組
Map<String, List<StreamItem>> streamMap1 = streamList.stream().collect(Collectors.groupingBy(StreamItem::getKey));
System.out.println(streamMap1);
//輸出:
{k1=[StreamItem{id=1, key='k1', name='i_1|k_k1'}, StreamItem{id=2, key='k1', name='i_2|k_k1'}], k2=[StreamItem{id=3, key='k2', name='i_3|k_k2'}, StreamItem{id=4, key='k2', name='i_4|k_k2'}]}
List 默認(rèn)分組過后是 Map<Key, Object>
//1.2分組只拿第一個(gè)
Map<String, StreamItem> streamMap2 = Stream.of(
new StreamItem(1, "k1"),
new StreamItem(2, "k2")).collect(Collectors.toMap(StreamItem::getKey, Function.identity()));
//如果 key 重復(fù)報(bào): java.lang.IllegalStateException: Duplicate key
System.out.println(streamMap2);
//輸出:
{k1=StreamItem{id=1, key='k1', name='i_1|k_k1'}, k2=StreamItem{id=2, key='k2', name='i_2|k_k2'}}
分組,在組內(nèi)排序然后獲取最大值,或者最小值
Comparator<StreamItem> idComparator =Comparator.comparing(StreamItem::getId);
Map<String, Optional<StreamItem>> streamMap3 = streamList.stream().collect(Collectors.groupingBy(StreamItem::getKey,
Collectors.reducing(BinaryOperator.maxBy(idComparator))));
System.out.println(streamMap3);
//輸出
{k1=Optional[StreamItem{id=2, key='k1', name='i_2|k_k1'}], k2=Optional[StreamItem{id=4, key='k2', name='i_4|k_k2'}]}
List 轉(zhuǎn)換為 List
這個(gè)也是超級(jí)實(shí)用的 api
List<List<StreamItem>> partitionList = Lists.partition(streamList, 2);
List<StreamItem> streamList1 = partitionList.stream().flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(streamList1);
//輸出
[StreamItem{id=1, key='k1', name='i_1|k_k1'}, StreamItem{id=2, key='k1', name='i_2|k_k1'}, StreamItem{id=3, key='k2', name='i_3|k_k2'}, StreamItem{id=4, key='k2', name='i_4|k_k2'}]
排序
排序,默認(rèn)正序,如果是需要倒序,可以在comparing 方法后面再調(diào)用 reversed 方法
//3.1 正序
List<StreamItem> streamList2 = Stream.of(
new StreamItem(3, "k1"),
new StreamItem(1, "k1"),
new StreamItem(2, "k2"))
//倒序:Comparator.comparing(StreamItem::getId).reversed()
.sorted(Comparator.comparing(StreamItem::getId)).collect(Collectors.toList());
System.out.println(streamList2);
去重
去重復(fù)后,保留最后寫入的值
//4.1 去重復(fù)
List<StreamItem> streamList3 = Stream.of(
new StreamItem(3, "k1"),
new StreamItem(1, "k1"),
new StreamItem(2, "k2"))
//如果只需要保留最大的 id 的值,就可以先排序, 時(shí)間復(fù)雜度考了個(gè)人覺得實(shí)用 group 更優(yōu)
.sorted(Comparator.comparing(StreamItem::getId).reversed())
.collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
//利用 set 特征去重
new TreeSet<>(Comparator.comparing(StreamItem::getKey))), ArrayList::new));
System.out.println(streamList3);
//輸出:
[StreamItem{id=3, key='k1', name='i_3|k_k1'}, StreamItem{id=2, key='k2', name='i_2|k_k2'}]
其他常用 API
- filter(按照條件過濾需要數(shù)據(jù))
- max(取出流中的最大值)
- min(取出流中的最小值)
- count(取出流中的數(shù)量)
- sum(取出流中數(shù)據(jù)的和)
- average(取出流中數(shù)據(jù)的平均值)
- distinct(將流中的數(shù)據(jù)去重)
- sorted(自然排序,默認(rèn)為升序,可以設(shè)置為升序排序或者降序排序)
- limit,skip (限制和跳過:可以將流數(shù)據(jù)的部分截取,可用于后臺(tái)的分頁場景)
- map(映射轉(zhuǎn)換)
- collect,toList(不可以對(duì)集合去重)
- collect, toSet(可以集合去重)
- toArray(將流數(shù)據(jù)轉(zhuǎn)為數(shù)組)
- mapToInt,distinct(將流數(shù)據(jù)轉(zhuǎn)成IntStream,并去重)
- reduce 求和
- reduce 求最大值
- reduce 求最小值
- reduce 求乘積
- findFirst(查找第一個(gè)元素)
- findAny(任意查找一個(gè)元素)
- allMatch(判斷是否全部滿足條件,全部滿足返回 true,否則返回false)
- anyMatch(判斷是否有一個(gè)滿足條件,只要有一個(gè)滿足就返回 true,否則都不滿足返回false)
- noneMatch(判斷是否都不滿足條件,都不滿足返回true,否則返回false)
- flatmap(扁平化流處理)