Stream

  • 流是即时计算的,按需提供,要什么生产什么。集合得先生产好所有的再使用。
    集合里的元素必须是计算出来的,真实存在内存中。流则是在概念上固定的数据结构(你不能添加或删除元素),其元素则是按需计算的,要什么就算什么。
  • 流只能遍历一次,遍历完就被消费了,无法第二次使用,只能重新再获取一次。
  • 外部迭代是一个一个判断,去遍历,流的内部迭代类似直接下命令:全部进行XXX操作。内部迭代时,项目可以透明地并行处理,或者用更优化的顺 序进行处理
  • Stream接口定义了许多操作
    • 中间操作
      • 如filter或sorted等中间操作会返回另一个流,这让多个操作可以连接起来形成一个查询。除非流水线上触发一个终端操作,否则中间操作不会执行任何处理。中间操作一般都可以合并起来,在终端操作时一次性全部处理。
    • 终端操作
      • 终端操作会从流的流水线生成结果。其结果为任何不是流的值,比如List、Integer,甚至void
    • 循环合并
      • 如filter和map是两个独立的操作,但是可以合并到一次遍历中。看起来是这样
filtering pork
mapping pork
filtering beef
mapping beef
filtering chicken
mapping chicken
  • 接口
    • filter() 筛选
    • map() 映射、获取值
    • limit() 取前几项
    • sorted() 排序
    • Arrays.stream() 接受数组并把数组转换为类型流(如把String数组转化为String流)
    • distinct() 去除重复元素
  • 扁平化
    • flatmap方法把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流。
    • map方法
  • 查询和匹配
    • allMatch 所有元素都和谓语匹配
    • antMatch 至少一个元素都不和谓语匹配
    • noneMatch 所有元素都不和谓语匹配
  • 归约(将流中所有元素反复结合起来,最终得到一个值)
    • reduce
      • (1, (a, b) -> a * b) 所有元素相乘
      • (0, (a, b) -> a + b) 所有元素相加
      • reduce(Integer::max)
      • reduce(Integer::min) 等于(x, y) -> x < y ? x : y
    • count() 统计流中的元素的个数
  • 原始类型流特化(避免暗含的装箱)
    • IntStream、DoubleStream和 LongStream,分别将流中的元素特化为int、long和double
    • 将流转换为特化版本的常用方法是mapToInt、mapToDouble和mapToLong。
    • 转回非特化流
      • Stream stream = intStream.boxed();
  • 数值范围
    • range(起始数值, 结束数值) 不包括结束数值,(1, 5)只取一到4
    • rangeClosed(起始数值, 结束数值) 包括结束数值,(1, 5)取一到5
  • 预定义收集器(如groupingBy)
    • 将元素归约汇总为一个值、元素分组、元素分区
    • 汇总 .collect(summingInt(Dish::getCalories))
    • 平均数 .collect(averagingInt(Dish::getCalories));
  • summarizing操作,一次就能收集总数、min、max、平均数
    • .collect(summarizingInt(Dish::getCalories)) 这个收集器会把所有这些信息收集到一个叫作IntSummaryStatistics的类里,它提供了 方便的取值(getter)方法来访问结果。
      菜单练习中打印IntSummaryStatistics的结果
IntSummaryStatistics{count=9, sum=4300, min=120, average=477.777778, max=800} 
  • 连接字符串
    • joining工厂方法返回的收集器会把对流中每一个对象应用toString方法得到的所有字符 串连接成一个字符串
    • joining在内部使用了StringBuilder来把生成的字符串逐个追加起来
    • .collect(joining(", ")); 重载方法,使用分隔符增加可读性
menu.stream().map(Dish::getName).collect(joining());          
menu.stream().collect(joining());       // 类中有toString方法就不需要手动提取。
menu.stream().collect(joining(", "));       //加入分隔符
  • 自定义收集器(定义自己的Collector接口)
public interface Collector<T, A, R>{ 
    Supplier supplier(); 
    BiConsumer accumulator(); 
    Function finisher(); 
    BinaryOperator combiner(); 
    Set characteristics(); 
} 
	- T是流中要收集的元素的类型
	- A是累加器的类型,累加器是在收集过程中用于累加结果的对象
	- R是收集得到的最终结果的类型
- supplier方法:返回一个空的累加器作为收集过程的容器
public Supplier<List<T>> supplier() { 
    return ArrayList::new; 
}
- accumulator方法 :将元素添加到结果容器
public BiConsumer<List<T>, T> accumulator() { 
    return (list, item) -> list.add(item); 
}

public BiConsumer, T> accumulator() {
    return List::add;
}
- finisher方法:对收集容器进行最终的转换,成为结果容器
public Function<List<T>> finisher(){
  return Function.identity();
}
// 当累加器对象与结果对象符合时,无需进行转换操作,直接调用identity函数。
- combiner方法:将拆分出来的并行流进行归约操作,最终合并到一起。
public BinaryOperator<List<T>> combiner() {
    return (list1, list2) -> {list1.addAll(list2); return list1;}
}
  • characteristics方法
    • characteristics会返回一个不可变的Characteristics集合,它定义 了收集器的行为——尤其是关于流是否可以并行归约,以及可以使用哪些优化的提示。 Characteristics是一个包含三个项目的枚举
      • UNORDERED——归约结果不受流中项目的遍历和累积顺序的影响。
      • CONCURRENT——accumulator函数可以从多个线程同时调用,且该收集器可以并行归 约流。如果收集器没有标为UNORDERED,那它仅在用于无序数据源时才可以并行归约。
      • IDENTITY_FINISH——这表明完成器方法返回的函数是一个恒等函数,可以跳过。这种 情况下,累加器对象将会直接用作归约过程的最终结果。这也意味着,将累加器A不加检 查地转换为结果R是安全的。
  • collect方法的重载
    • Stream有一个重载的collect方法可以接受另外三个函数——supplier、 accumulator和combiner,其语义和Collector接口的相应方法返回的函数完全相同。不能传递任何Characteristics,所以它永远都是一个IDENTITY_FINISH和 CONCURRENT但并非UNORDERED的收集器。
例:
List<DIsh> dishes = menuStream.collect(
                        ArrayList::new,
                        List::add,
                        List::addAll);

未完待续...

posted @   Instser  阅读(117)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示