Java8新特性:stream流应用,丢掉for循环实现复杂遍历功能
admin
2024-03-14 03:22:03
0

stream流

stream流是支持数据处理操作的数据源生成的元素序列,这些数据源可以是集合、数组、文件I/O channel等。stream不是一种数据结构,也不会存储数据,并且它支持数据聚合操作,如过滤filter、映射map、去重distinct、匹配match等等。

stream流操作可以分为,生成stream流、操作stream流(中间操作和终端操作)。

生成stream

有两种方式创建stream

  1. stream() − 为集合创建串行流。
  2. parallelStream() − 为集合创建并行流。

通过集合生成

集合实例后面直接.stream()就可以非常方便的创建一个stream。比如List、Set、Map集合都可以通过这种方式创建stream。

List list = Arrays.asList("欢迎阅读", "鳄鱼儿"); 
list.stream();
list.parallelStream()

通过数组生成

使用Arrays.stream()方法生成流,生成流的类型是数值流IntStream。除了IntStreamLongStream DoubleStream

int[] arr = new int[]{1,2,3};
IntStream stream = Arrays.stream(arr);

通过文件生成

通过Files.lines(path, Charset)生成stream。

注意:此时生成的流需要需要手动关闭,通过一个BaseStream.close()方法和实现AutoCloseable。一般来说几乎所有的流实例实际上不需要在使用后关闭,只有来源为I/O channel的流才需要如此。

Stream lines = Files.lines(Paths.get("./test.txt"), Charset.defaultCharset());

流的操作

stream操作类型分为两种,中间操作和终端操作。

中间操作

中间操作即代表一个stream后返回的还是stream,其后面仍可以跟随中间操作,比如过滤filter后仍可以接distinct去重。

filterdistinctsortedlimitskip

通过以下代码展示filterdistinctsortedlimitskip的用法。

  1. 通过filter过滤掉小于2的元素
  2. 通过distinct去掉重复的元素
  3. 通过sorted对元素从小到大排序
  4. 通过skip忽略掉前2个元素
  5. 再通过limit截取前5个元素
  6. 最后通过forEach进行遍历输出。
  7. 输出结果为:4
    6
    8
    12
    55
public static void main(String[] args) {List list = Arrays.asList(1, 12, 6, 8, 4, 55, 6, 77, 66, 12);list.stream().filter(item -> item > 2)   // 过滤元素 1.distinct()                 // 去重 12.sorted()                   // 排序.skip(2)                    // 跳过流中元素 4 6.limit(5)                   // 保留前5个元素.forEach(System.out::println);  // 输出
}

mapmapToIntmapToLongmapToDoubleflatMap

map流映射,即将元素映射成另外一个新的元素,这是一种一对一关系。
flatMap流转换,即将一个流中的每个值都转换为另一个流,是一种一对多的关系.

比如参考以下代码

List stringList = Arrays.asList("欢迎 阅读", "鳄鱼儿 文章");
List strLen = stringList.stream().map(item -> item.length()).collect(Collectors.toList());
System.out.println(strLen);List newStrList = stringList.stream().flatMap(item -> Arrays.stream(item.split(" "))).collect(Collectors.toList());
System.out.println(newStrList);;

输出结果分别是

  1. [5, 6],String 转变成了 Integer
  2. [欢迎, 阅读, 鳄鱼儿, 文章],一个流中的每个值都转换为另一个流,最好组合成一个新的stream。

mapToIntmapToLongmapToDouble分别是返回一个IntStreamLongStreamDoubleStream
这些类型的stream包括一些sum()max()
min()方法等,可以用于计算,如下面代码求和示例:

List list = Arrays.asList(1, 12, 6, 8, 4, 55, 6, 77, 66, 12);
// 转换IntStream
list.stream().mapToInt(item -> item * 2).forEach(System.out::println); 
// 对IntStream内元素进行计算,并求和 
System.out.println(list.stream().mapToInt(item -> item * 2).sum());

peekforeach

peekforeach是对元素进行遍历处理的方法。

区别在于peek是中间操作,foreach是终端操作,

List list = Arrays.asList(1, 12, 6, 8, 4, 55, 6, 77, 66, 12);
// 如果没有终端操作,则peek不会执行
list.stream().peek(System.out::println);// 有终端操作,先执行peek,再返回count,最后通过println输出
System.out.println(list.stream().peek(System.out::println).count()
);
// foreach是终端操作
list.stream().forEach(System.out::println);

输出结果:

  1. 1 12 66 12
  2. 4
  3. 1 12 66 12

终端操作

终端操作即一个stream的终止(关闭),一个stream中只能有一个终端操作。

allMatchanyMatchnoneMatch

  1. allMatch:匹配所有元素
  2. anyMatch:匹配其中一个元素
  3. noneMatch:全部元素都不匹配,跟allMatch相反
List integerList = Arrays.asList(1, 3);if (integerList.stream().allMatch(i -> i > 5)) {System.out.println("所有元素值都大于5");
} else {System.out.println("并非所有元素值都大于5");
}if (integerList.stream().anyMatch(i -> i > 5)) {System.out.println("存在值大于5的元素");
} else {System.out.println("不存在值大于5的元素");
}if (integerList.stream().noneMatch(i -> i > 5)) {System.out.println("元素值都小于5");
} else {System.out.println("元素值不都小于5");
}

输出结果:

  1. 并非所有元素值都大于5
  2. 不存在值大于5的元素
  3. 元素值都小于5

countmaxmin

  1. count: 统计流中元素个数
  2. max: 获取流中最大值
  3. min: 获取流中最小值
List stringList = Arrays.asList("欢迎 阅读", "鳄鱼儿 文章");Optional min = stringList.stream().map(String::length).min(Integer::compareTo);stringList.stream().mapToInt(String::length).min();

有两种写法,通过传参min(Comparatorcomparator)。或者转换成为IntStream再进行min操作。

findAnyfindFirst

  1. findAny:从符合条件的元素中,随机查找到一个元素
  2. findFirst:根据条件查找到符合条件的第一个元素
List list = Arrays.asList(1, 12, 66, 12);System.out.println(list.stream().filter(i -> i > 3).findFirst().orElse(-1));
System.out.println(list.stream().filter(i -> i > 3).findAny().orElse(-1));

结果输出:

  1. 12
  2. 12

总结

到此,基础Stream用户就已经说完了,看到这里我们会发现,所以的stream其实都可以用for循环来实现,而我们全篇都没有使用for循环来实现,这些如果用for循环实现,你会发现实现的语句变得复杂了很多,不信的话,你可以试试。

我们也可以看到stream带来的好处,包括代码更简洁解耦等。

相关内容

热门资讯

银行间主要利率债午间走势分化 每经AI快讯,7月28日,银行间主要利率债午间走势分化,30年期国债“26超长特别国债04”收益率下...
2026海河国际消费论坛即将在... 2026海河国际消费论坛将于7月30日下午在天津启幕,目前各项筹备工作已全部就绪。本届论坛以“创新服...
原创 一... 前言 1942年的一天,一名身穿军装的年轻人,悄悄走到一位老妇人的面前。他脸上带着疲惫,眼神中却依然...
原创 曹... 八十岁的曹德旺,这几年在公开场合谈到房子这两个字,语气一次比一次冷。他早年那句"房子不过是钢筋水泥堆...
股息率近5.5%!港股红利低波... 7月28日,港股红利资产延续强势。截至13时48分,港股红利低波ETF招商(520550)涨0.46...
企业文件共享平台怎么选?主流方... 文件共享平台种类繁多,各有侧重。今天这篇文章,把2026年市面上主流的企业文件共享平台做个系统梳理,...
币圈院士:7.26以太坊(ET... 币圈院士:7.26以太坊(ETH)双周期指标暗藏方向,行情即将破位?最新行情分析参考 以太坊现价18...
老铺黄金发盈喜后股价跌16.2... 观点网讯:7月28日,老铺黄金股价裂口低开12.97%,最低见325.8港元,收盘报332港元,跌1...
苏泊尔上半年营收净利双降,法籍... 瑞财经 严明会 近日,苏泊尔(002032.SZ)披露2026年半年度业绩快报。 公告显示,公司上半...
IPO雷达|陕西瑞科回复二轮问... 深圳商报·读创客户端记者 梁佳彤 7月27日,据北交所官网,陕西瑞科新材料股份有限公司(下称“陕西瑞...
普京签令,俄军扩编 据新华社报道,俄罗斯总统普京27日签署命令, 决定组建几支军事建筑工程部队,并将俄武装力量编制总人数...
2027年德国杜塞尔多夫国际铸... 展会名称:2027年德国杜塞尔多夫国际铸造、冶金、热处理及铸件展览会GMTN 开始时间:2027-0...
郑州有了温通刮痧培训示范基地 本报讯(记者 杨振东 通讯员 张丹婧)温通刮痧是中医外治法里的一种,简单说就是在传统刮痧基础上,结合...
整箱茅台和单瓶茅台,回收行情为... 不少天津藏友存在疑惑:同样年份、同样品相的飞天茅台,整箱装和拆箱单瓶的回收报价存在差距,不清楚背后的...
北京五粮液收购需要遵循哪些通用... 北京五粮液收购的行业背景 近年来高端白酒的收藏与流通市场规模稳步扩张,北京作为国内重要的消费城市,五...
微软CEO重磅警告:只依赖一家... 来源:环球网 【环球网科技综合报道】7月28日消息,据外媒TechCrunch报道,微软CEO萨提亚...
策略师:金价夏季维持4000美... 汇通财经APP讯——今夏金价大概率在4000美元/盎司附近震荡筑底,市场等待美联储货币政策清晰指引。...
大众叙事下白酒行业周期如何拆解... 白酒行业的波动往往并非单纯由供需关系决定,而是 宏观经济预期与 渠道库存周期共振的结果。在大众认知中...
沈皓南:黄金低位大区间运行,短... 大家好,我是沈皓南,差不多有一个月没有更新黄金文章了,这段时间我去了美丽的新疆,自驾了独库公路,观赏...
原创 上... 2000年9月28日傍晚,济青高速临淄出口边一家小饭馆的木门被推开,六个山东汉子鱼贯而入。几个小时前...