NipGeihou's blog NipGeihou's blog
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档

NipGeihou

我见青山多妩媚,料青山见我应如是
  • Java

    • 开发规范
    • 进阶笔记
    • 微服务
    • 快速开始
    • 设计模式
  • 其他

    • Golang
    • Python
    • Drat
  • Redis
  • MongoDB
  • 数据结构与算法
  • 计算机网络
  • 应用

    • Grafana
    • Prometheus
  • 容器与编排

    • KubeSphere
    • Kubernetes
    • Docker Compose
    • Docker
  • 组网

    • TailScale
    • WireGuard
  • 密码生成器
  • 英文单词生成器
🍳烹饪
🧑‍💻关于
  • 分类
  • 标签
  • 归档
  • 设计模式

  • 开发规范

  • 经验分享

  • 记录

  • 快速开始

  • 笔记

    • 多线程与并发

    • JDK

      • Stream
        • 操作
          • 创建
          • 中间操作
          • 过滤 filter
          • 截断 limit
          • 跳过 skip
          • 去重 distinct
          • 映射 map
          • 映射解构 flatMap
          • 排序 sorted
          • 终止操作
          • 是否所有元素满足断言 allMatch
          • 是否至少一个元素满足断言 anyMatch
          • 是否没有元素满足断言 noneMatch
          • 返回第一个元素 findFirst
          • 返回任意一个元素 findAny
          • 返回元素总个数 count
          • 返回元素中最小值 min
          • 返回元素中最大值 max
          • 返回元素中之和 sum
          • 归约 reduce
          • 收集
        • 场景应用
        • 参考资料
      • 「Java」Lambda表达式与函数式编程
      • Javadoc
    • Java集合

    • Spring

    • JVM

    • Other

  • 面试题

  • 微服务

  • 踩过的坑

  • Java
  • 笔记
  • JDK
NipGeihou
2022-08-12
目录

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);

# 场景应用

  1. 将长度为 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());
  1. 返回 A 对象列表中的 B 对象列表集合
List<Integer> productIdList = responseList.stream()
                .flatMap(o -> o.getOrderInfoList().stream().map(OrderInfoResponse::getProductId))
                .distinct()
                .collect(Collectors.toList());
  1. 根据 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())));
  1. 按列表的某个字段统计起出现的次数
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)));

# 参考资料

  1. Java 8 Stream | 菜鸟教程 (opens new window)
上次更新: 2024/01/16, 18:00:00
Java多线程 - 线程变量传递ThreadLocal
「Java」Lambda表达式与函数式编程

← Java多线程 - 线程变量传递ThreadLocal 「Java」Lambda表达式与函数式编程→

最近更新
01
Docker Swarm
04-18
02
安全隧道 - gost
04-17
03
Solana最佳实践
04-16
更多文章>
Theme by Vdoing | Copyright © 2018-2025 NipGeihou | 友情链接
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式