首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

同事老喜欢用Stream流,咋弄。。。

最近我刷到一个程序员讨论的热点话题,说是有个同事喜欢用Stream流,结果整得代码难读得不行。

甚至还有人建议“反向升级JDK到1.7”,我当时看得直乐呵。

但是说实话,这个现象其实在职场上挺常见的。

写代码嘛,大家都有自己的风格,有人爱用流是觉得它写起来简洁优雅,有人讨厌流是觉得它让代码变得迷雾重重。

今天咱们就从技术的角度来好好聊聊,看看Stream流到底该怎么用,怎么才能不把自己坑得太惨。

首先,得给Stream流正个名。自从JDK 8推出以来,Stream流就火得不行。它的最大特点在于可以用声明式编程的方式处理数据流,不用写那些冗长的for循环,只需要链式调用几行代码,就能搞定过滤、转换、分组等操作。

举个栗子,如果你要找出一个List里所有以字母“A”开头的名字,用传统的for循环可能得这样写:

List<String> names = Arrays.asList("Alice", "Bob", "Andrew", "Tom");List<String> result = new ArrayList<>();for (String name : names) { if (name.startsWith("A")) { result.add(name); }}

但是如果用Stream流,这么优雅的一行就搞定了:

看,多简洁优雅啊!

所以说,Stream流在处理一些简单的集合操作时确实是个神器,比如过滤、排序、分组、去重等,简直就是写代码的艺术享受。

然而,流这种东西,确实不是万能药。

它适合处理简单的数据操作,但要是用来搞复杂的业务逻辑,那简直就是“自讨苦吃”。我还记得之前有个同事喜欢用Stream做各种复杂操作,甚至连遍历两次集合、合并数据的简单需求都能写成这样:

Map<Integer, String> firstMap = firstList.stream() .collect(Collectors.toMap(Item::getId, Item::getName));

List<ResultItem> results = secondList.stream() .map(item -> new ResultItem(item.getId(), firstMap.get(item.getId()), item.getValue())) .collect(Collectors.toList());

看上去没啥毛病吧?

但问题就在于频繁调用firstMap.get()。如果secondList很大,而firstList小,这段代码的性能就会受影响。

而且如果某个ID在firstMap里没有对应的值,你很可能会卡在null问题上,调试起来非常麻烦。更别说如果有多层嵌套的流操作,代码读起来简直就是地狱🤯。

那有人可能会说:“不用Stream,难道还要回到原始的for循环时代吗?”

其实不然。对于复杂业务逻辑,for循环反而更清晰直观。

来看个例子,如果我们要合并两个不同集合并做交叉操作,传统方法是这样的:

List<ResultItem> result = new ArrayList<>();for (Item first : firstList) { for (Item second : secondList) { if (first.getId().equals(second.getId())) { result.add(new ResultItem(first.getId(), first.getName(), second.getValue())); } }}

虽然是双层循环,但逻辑一目了然。而用Stream流来写,可能会变成这样:

List<ResultItem> result = firstList.stream() .flatMap(first -> secondList.stream() .filter(second -> first.getId().equals(second.getId())) .map(second -> new ResultItem(first.getId(), first.getName(), second.getValue()))) .collect(Collectors.toList());

你看,光是读一遍就觉得烧脑,尤其是对维护代码的同事来说,这段代码可能让人抓狂。那种“花里胡哨”的写法,真不是每个人都能欣赏得了的。

关于性能方面,Stream流在集合规模较小的时候确实表现不错,但一旦数据量上来,频繁的集合转换和Lambda表达式创建反而会拖累性能。

另外,流的调试也不像for循环那么方便。如果你想找出流操作的哪一步出问题了,可能得层层剥离,甚至打很多断点,这个过程简直比改需求还痛苦。

# 如何正确使用Stream流

既然说了这么多流的“缺点”,是不是就意味着它一无是处了呢?当然不是。

Stream流的优势在于简化一些常见的数据操作,比如:

过滤和转换:简单的筛选和转换,流的写法能让代码更简洁。

分组和排序:用Collectors.groupingBy()和sorted()可以轻松实现分组和排序。

组合操作:如果处理链条明确,而且每个操作都能一眼看懂,那流的用法还是值得一试的。

但对于复杂业务逻辑,如多级嵌套、跨集合操作或者需要做大量的条件判断,还是老老实实用for循环吧。

最关键的是,代码的核心价值在于“可读性”和“可维护性”,而不是为了看起来“酷”而滥用某个技术。

总的来说,流是个好工具,但也得用对地方。

如果用Stream能让代码更直观易读,那它就是个好帮手。反之,如果流的写法让逻辑变得复杂,那就果断放弃。

写代码是为了让人读的,不是为了显摆技术有多炫酷。希望大家在使用Stream流的时候能多考虑一下代码的可读性,这才是写好代码的关键所在。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O_9eAsE3Lac4nWmOe5W2nb_A0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券