这种去重方法真的有用么

2022-07-06 16:20:48 +08:00
 luxinfl

为什么 copy 下来运行就报错,空指针,不清楚在网上的例子是怎么跑的

studentList = studentList.stream().collect(
  Collectors.collectingAndThen(
     Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new));
    

不知道为啥 string 类型字段就报错空指针,int 没错。

就是为了要去重重复对象,重复对象的判断条件是某个字段的值相同。找了好多都是这么写的,但是一跑就报错。很神奇。

3538 次点击
所在节点    程序员
22 条回复
AoEiuV020CN
2022-07-06 16:34:01 +08:00
最好上个完整一点点的代码,
然后是哪个对象在哪里空了,期望是什么,
这里 stream 可读性很糟糕,不如 for 循环,或者 addAll ,
luxinfl
2022-07-06 16:39:33 +08:00
@AoEiuV020CN 我搞出来了,tm 是别人传的数据有问题。。一个列表里面有个对象搞错字段了。。。
nothingistrue
2022-07-06 17:04:09 +08:00
原理是,利用 Set 不允许添加重复元素的特性(添加重复元素时忽略,不是报错)来去重。具体操作是,将当前集合的所有元素尝试全部放入一个 Set 中(用哪个 Set 的实现类取决于如何判重),然后在将完成的 Set 转换回原来的集合,在将元素放入到 Set 中的时候,重复元素会被排除掉。但是你抄这段代码可读性是真特么差。
nothingistrue
2022-07-06 17:13:24 +08:00
尝试换一种写法:

studentList = new TreeSet<>(Comparator.comparing(Student::getName)).addAll(studentList).stream().collect(Collectors.toList())
zhuangzhuang1988
2022-07-06 17:20:00 +08:00
还是写简单的 foreach 吧
这样看真难看懂
《 effective java 》里也有 stream 的讨论,不要无脑 stream
codingadog
2022-07-06 17:21:01 +08:00
数据量不大的话不如直接 removeIf 。

Set<String> tmp = new HashSet<>();
studentList.removeIf(student -> !tmp.add(student.getName()));
Leviathann
2022-07-06 17:23:00 +08:00
换个库把,stream 除了 parallel 功能,其他完全没 eclipse collection 好用,性能也不如,java 官方的视频都说 eclipse collection 的抽象程度更高且性能也更好
nothingistrue
2022-07-06 17:28:09 +08:00
好吧,我写错了,addAll 不能链式操作,要想一句代码就完成的话,只能使用原先那段很难看的代码。为了可读性建议拆分语句如下:

TreeSet<Student> tempSet = new TreeSet<>(Comparator.comparing(Student::getName));
tempSet.addAll(studentList);
studentList = new ArrayList(tempSet); // 或者 studentList = tempSet.stream().collect(Collectors.toList());
xinhochen
2022-07-06 17:42:20 +08:00
我觉得这样写更容易理解一些:
Set<String> filter = new HashSet<>();
List<Student> result = studentList.stream().filter(o -> filter.add(o.getName())).collect(Collectors.toList());
rpish
2022-07-06 17:45:58 +08:00
好奇问下,大家项目开发中 stream 用得多吗?
Red998
2022-07-06 17:55:44 +08:00
用的很多 jdk8 stream 流用的很多
chendy
2022-07-06 18:04:08 +08:00
studentList = new ArrayList<>(new HashSet<>(studentList));
mazai
2022-07-06 18:06:20 +08:00
只是因为 students 中 name 有 null 的学生吧。 还有只是去重不用这么麻烦,重写 Student 对象的 hashcode 和 equals 方法,studentList.stream().distinct().collect(Collectors.toList()); 就行了
git00ll
2022-07-06 18:41:46 +08:00
这么写可读性贼差
golangLover
2022-07-06 19:22:15 +08:00
@mazai 同意有 null 的解释
但不同意重写 equal. 可能我只是需要比较这个属性一次
potatowish
2022-07-06 19:28:24 +08:00
@git00ll 可以抽一个常用的方法出来,每次这么写一堆确实难受
lmshl
2022-07-06 21:42:24 +08:00

归根结底还是 Java 设计的 API 太丑了,丑破天际,搁 Scala 里就一行的事
val result = studentList.distinctBy(_.name)
wolfie
2022-07-07 11:32:55 +08:00
骚操作 new ArrayList(toMap(getName()).values())
Anshay
2022-07-07 11:39:39 +08:00
直接 studentList.stream().distinct.toCollect.....即可,前提是有自己编写了 studentList 中的 equals 方法和 hashCode 方法。
mazai
2022-07-07 14:19:56 +08:00
@golangLover equals 和 hashcode 具体选取哪些字段重写还是看业务,哪几个字段能代表学生的唯一性,那就重写哪几个字段

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/864461

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX