Stream
笔记
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
换言之:可以把一个集合,修改对象的属性、抽取对象某一个属性返回新列表、排序、过滤等功能的链式操作工具类。
# 操作
List<String> list = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
# 创建
stream()
− 为集合创建串行流(单线程)。parallelStream()
− 为集合创建并行流(多线程)。
Stream<String> stream = list.stream();
# 中间操作
不会执行任何操作
# 过滤 filter
返回断言匹配的元素组成的流
Stream<T> filter(Predicate<? super T> predicate)
# 截断 limit
返回由该流的元素组成的流,截断长度不超过 maxSize
Stream<T> limit(long maxSize);
笔记
流操作并非是先全部完成一个操作,再传递到另一个操作,比如
studentList.stream()
.filter(student -> student.getAge() > 20)
.limit(1)
.forEach(System.out::println);
在上述代码中,先过滤找出所有 大于20
的同学,再截取 1
条记录,由 debug 知,当 filter
找到 1
条满足断言条件的数据后,不再断言。
# 跳过 skip
在丢弃流的前 n 个元素后,返回由该流的剩余元素组成的流。如果此流包含少于 n 个元素,则将返回一个空流。
Stream<T> skip(long n);
# 去重 distinct
返回由该流的不同元素(根据 Object.equals(Object)
)组成的流。
Stream<T> distinct();
# 映射 map
根据 Function 接口中返回的对象,组成一个新流。
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
# 映射解构 flatMap
把套娃流变成一个流,类似于 add()
和 addAll()
的区别
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
示例:
将列表对象的多个属性,放到一个集合中
list.stream()
.flatMap(student -> Stream.of(student.getCode(),student.getId())
))
.filter(str -> StrUtil.containsIgnoreCase(str, keyword))
.collect(Collectors.toSet());
# 排序 sorted
// 自然排序
Stream<T> sorted();
// 定制排序
Stream<T> sorted(Comparator<? super T> comparator);
# 终止操作
一次性执行全部内容,即 “惰性求值”
# 是否所有元素满足断言 allMatch
boolean allMatch(Predicate<? super T> predicate);
# 是否至少一个元素满足断言 anyMatch
boolean anyMatch(Predicate<? super T> predicate);
# 是否没有元素满足断言 noneMatch
boolean noneMatch(Predicate<? super T> predicate);
# 返回第一个元素 findFirst
Optional<T> findFirst();
# 返回任意一个元素 findAny
Optional<T> findAny();
# 返回元素总个数 count
long count();
# 返回元素中最小值 min
Optional<T> min(Comparator<? super T> comparator);
# 返回元素中最大值 max
Optional<T> max(Comparator<? super T> comparator);
# 返回元素中之和 sum
list.stream().mapToDouble(User::getHeight).sum();
// BigDecimal
bdList.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
# 归约 reduce
可以将流中元素反复结合起来,得到一个值。如累加
// identity 作为 accumulator 第一个入参
T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
# 收集
将流转换为其他形式。
<R, A> R collect(Collector<? super T, A, R> collector);
Collectors 常用实现
// 转列表
Collector<T, ?, List<T>> toList();
// 转去重集合
Collector<T, ?, Set<T>> toSet();
// 转指定collectionFactory的集合
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory);
// 总数
public static <T> Collector<T, ?, Long> counting();
// 平均值
public static <T> Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper);
// 总和
// 最大值
// 最小值
// 分组
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier);
// 多级分组
public static <T, K> Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier);
// 分区(按条件分区)
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate);
// 汇总
public static <T> Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper);
// 把String流连成一个字符串,可指定前后字符串、分隔字符串
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter)
场景 1:把 JSON 元素收集到 JSON 数组(收集到指定数组)
需求:将对象流收集到指定数组
JsonArray jsonArray = list.stream().map(e -> {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty(e.getDetailId().toString(), e.getSize());
return jsonObject;
}
).collect(JsonArray::new, JsonArray::add, JsonArray::addAll);
# 场景应用
- 将长度为 n 的对象 A 列表转换为长度大于 n 的对象 B 列表,如将 1 个对象 A 变成 2 个对象 B。
List<ObjectB> objectBList = ObjectAList.stream().flatMap(objectA -> {
ObjectB objectB1 = new ObjectB();
objectB1.setName(objectA.getName());
ObjectB objectB2 = new ObjectB();
objectB2.setName(objectA.getTitle());
return Stream.of(objectB1, objectB2);
}).collect(Collectors.toList());
- 返回 A 对象列表中的 B 对象列表集合
List<Integer> productIdList = responseList.stream()
.flatMap(o -> o.getOrderInfoList().stream().map(OrderInfoResponse::getProductId))
.distinct()
.collect(Collectors.toList());
- 根据
A.orderId
分组,Value 为List<OrderDetail>
中的List<OrderDetail.Sn>
列表的 X 集合
public class NftCollectionOrderDetail {
private Long id;
private Long orderId;
private Integer collectionSn;
}
// 按orderId分组, snList
Map<Long, List<Integer>> collectionOrderDetailMap = collectionOrderDetailList.stream()
.collect(Collectors.groupingBy(NftCollectionOrderDetail::getOrderId, Collectors.mapping(NftCollectionOrderDetail::getCollectionSn, Collectors.toList())));
- 按列表的某个字段统计起出现的次数
Map<String, Long> taskLogByPlatformMap = taskLogList.stream()
.map(l -> shopMap.get(l.getShopId()))
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
Map<String, Integer> taskLogByPlatformMap = taskLogList.stream()
.map(l -> shopMap.get(l.getShopId()))
.collect(Collectors.groupingBy(s -> s, Collectors.summingInt(e -> 1)));
# 参考资料
上次更新: 2024/01/16, 18:00:00