这种去重方法真的有用么 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
luxinfl
V2EX    程序员

这种去重方法真的有用么

  •  
  •   luxinfl 2022-07-06 16:20:48 +08:00 4197 次点击
    这是一个创建于 1251 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

    Set<String> tmp = new HashSet<>();
    studentList.removeIf(student -> !tmp.add(student.getName()));
    Leviathann
        7
    Leviathann  
       2022-07-06 17:23:00 +08:00
    换个库把,stream 除了 parallel 功能,其他完全没 eclipse collection 好用,性能也不如,java 官方的视频都说 eclipse collection 的抽象程度更高且性能也更好
    nothingistrue
        8
    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
        9
    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
        10
    rpish  
       2022-07-06 17:45:58 +08:00
    好奇问下,大家项目开发中 stream 用得多吗?
    Red998
        11
    Red998  
       2022-07-06 17:55:44 +08:00   1
    用的很多 jdk8 stream 流用的很多
    chendy
        12
    chendy  
       2022-07-06 18:04:08 +08:00
    studentList = new ArrayList<>(new HashSet<>(studentList));
    mazai
        13
    mazai  
       2022-07-06 18:06:20 +08:00
    只是因为 students 中 name 有 null 的学生吧。 还有只是去重不用这么麻烦,重写 Student 对象的 hashcode 和 equals 方法,studentList.stream().distinct().ollect(Collectors.toList()); 就行了
    git00ll
        14
    git00ll  
       2022-07-06 18:41:46 +08:00
    这么写可读性贼差
    golangLover
        15
    golangLover  
       2022-07-06 19:22:15 +08:00 via Android
    @mazai 同意有 null 的解释
    但不同意重写 equal. 可能我只是需要比较这个属性一次
    potatowish
        16
    potatowish  
       2022-07-06 19:28:24 +08:00 via iPhone
    @git00ll 可以抽一个常用的方法出来,每次这么写一堆确实难受
    lmshl
        17
    lmshl  
       2022-07-06 21:42:24 +08:00

    归根结底还是 Java 设计的 API 太丑了,丑破天际,搁 Scala 里就一行的事
    val result = studentList.distinctBy(_.name)
    wolfie
        18
    wolfie  
       2022-07-07 11:32:55 +08:00
    骚操作 new ArrayList(toMap(getName()).values())
    Anshay
        19
    Anshay  
       2022-07-07 11:39:39 +08:00
    直接 studentList.stream().distinct.toCollect.....即可,前提是有自己编写了 studentList 中的 equals 方法和 hashCode 方法。
    mazai
        20
    mazai  
       2022-07-07 14:19:56 +08:00
    @golangLover equals 和 hashcode 具体选取哪些字段重写还是看业务,哪几个字段能代表学生的唯一性,那就重写哪几个字段
    issakchill
        21
    issakchill  
       2022-07-07 14:46:29 +08:00
    streamEx 有些方法还挺好用的 也自带根据某字段去重的方法
    golangLover
        22
    golangLover  
       2022-07-08 21:29:58 +08:00 via Android
    @mazai 。。你是不可能一两次比较就重写字段的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3008 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 13:00 PVG 21:00 LAX 05:00 JFK 08:00
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86