千万不要滥用Stream.toList(),它有坑!
发布时间:2025-05-21 04:59:42 发布人:远客网络
一、千万不要滥用Stream.toList(),它有坑!
1、在处理Java集合操作时,stream.toList()与collect(Collectors.toList())的使用需谨慎。不当使用可能导致UnsupportedOperationException异常,尤其在后续对结果进行添加、修改操作时。
2、从Java16版本开始,stream.toList()提供了一种更简洁的转换方式,但其本质是通过Collections.unmodifiableList方法生成不可变的List。这意味着任何对list的set、add或remove操作都会抛出UnsupportedOperationException异常。
3、对比之下,collect(Collectors.toList())返回的是可变的ArrayList实例,适用于后续进行各种操作。但需注意,若不提供指定的Supplier,返回的仍是ArrayList类型。
4、此外,List.of()方法同样生成不可变的list。对于创建不可变列表的需求,of和List.copyOf提供了便捷的静态工厂方法。
5、为了确保代码的健壮性与兼容性,推荐在确定结果只用于读取时使用stream.toList()。如果需要后续修改或操作,则应采用collect(Collectors.toCollection(ArrayList::new))方式代替collect(Collectors.toList()),以避免警告并确保代码的灵活性。
二、java for循环 怎样把一个list里相同的数据放到一起
1、通过题主的描述可以看到,其实就是一个List<Integer>的集合数据处理问题,希望把相同的数据放到一起,是一种归类操作,也就是说其实总得需要把List<Integer>形式转化为Map<Integer, List<Integer>>的形式
2、这种形式map的key也就是当前的这个数字,而这个value就是这个数字对应的所有当前出现此key的集合
3、List<Integer>list=Arrays.asList(1,1,2,3,4,2,1);
4、Map<Integer,List<Integer>>map=newHashMap<>();
5、//map是否包含此key,若已经包含则添加一个新的数字到对应value集合中
6、//map不包含此key,则重新创建一个新集合,并把这个数字添加进集合
7、List<Integer>newList=newArrayList<>();
8、System.out.println(map);
输出结果
9、这只是简单把map打印出来,当然有了这个map,想怎么样输出都是可以的了
10、额外的,上面的那种写法虽然也还算简单明了,但是对于如今Java8中的流(Stream)操作而言,还是显得太复杂了,而且采用for这种外部循环告诉机器你要怎样循环怎么取值,怎样操作实在繁琐,太过命令式编程,若采用Stream的方式来写上述过程就非常简答了,只需要告诉机器你要做什么就可以了,不用去管怎么循环,只管要什么操作(把JDK升到8即可尝试以下代码)
11、Map<Integer,List<Integer>>map1=list.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.toList()));
12、System.out.println(map1);
一行代码就搞定了,这里采用的是Collectors.groupingBy方法进行归类数据,里面两个参数代表分别代表:
13、一行代码就搞定了,这里采用的是Collectors.groupingBy方法进行归类数据,里面两个参数代表分别代表:
14、如何把流中的数据进行归类,表示归类的依据,由于是数字本身,所以第一个参数传入Function.identity,就是代表本身的意思,数字相同就归类到一起
15、第二个参数是代表,把归类到一起的数字怎么合到一起,Collectors.toList代表就是把数字归类成集合,所以返回的就是Map<Integer, List<Integer>>,这正好是我们要的结果
16、由于Collectors.groupingBy默认是按照Collectors.toList的方式进行归类的,所以上面的代码还可以再减少一个参数,写为
17、Map<Integer,List<Integer>>map1=list.stream().collect(Collectors.groupingBy(Function.identity()));
18、System.out.println(map1);
结果为
19、结果也是一样的,题主可以自行选择
三、3种方法,用Java找出两个List中的重复元素
在Java编程中,我们经常会遇到需要找出两个列表(List)中重复元素的情况。本文将介绍三种方法来实现这一目标,以提升编程效率。
Java中的HashSet是一个不允许有重复元素的集合。我们可以利用这个特性,将两个List合并,然后通过计算合并后的集合与两个原始List的差集,来找出重复的元素。以下是一个使用HashSet来找出两个List中重复元素的代码示例。
set.retainAll(list2);//得到list1在list2中出现的元素
Java 8引入了Stream API,提供了更简洁的数据处理方式。我们可以使用Stream API的`distinct()`方法来去除重复元素,并通过`filter()`方法来识别两个List中的重复元素。以下是一个使用Stream API来找出两个List中重复元素的代码示例。
List distinctList= Stream.concat(list1.stream(), list2.stream())
.collect(Collectors.toList());
List duplicateList= distinctList.stream()
.filter(element-> list1.contains(element)&& list2.contains(element))
.collect(Collectors.toList());
还可以通过HashMap来识别重复元素。我们将每个元素作为键,其出现次数作为值存入HashMap。遍历HashMap时,找到出现次数大于1的元素,这些元素就是重复的。以下是一个使用HashMap来找出两个List中重复元素的代码示例。
map.put(element, map.getOrDefault(element, 0)+ 1);
map.put(element, map.getOrDefault(element, 0)+ 1);
List duplicates= map.entrySet().stream()
.filter(entry-> entry.getValue()> 1)
.collect(Collectors.toList());
以上三种方法均可有效地找出两个List中的重复元素,开发者可以根据实际情况选择最适合的方法。