【问题标题】:remove elements with repeated attribute using lambda expressions [duplicate]使用 lambda 表达式删除具有重复属性的元素
【发布时间】:2018-03-15 01:21:13
【问题描述】:

我有一个这样的 Person 对象列表:

list.add(new Person("John", 20)); //person is just name and age
list.add(new Person("Maria", 21));
list.add(new Person("John", 40));
list.add(new Person("Carl", 10));

无论年龄大小,生成的列表都必须没有同名的人,因此只有 3 个元素可以存活。如何使用 Java 8 lambda 表达式来实现这一点?

【问题讨论】:

    标签: java lambda java-8


    【解决方案1】:

    您可以尝试以下方法:

    Set<String> unique = new HashSet<>();
    list.removeIf(e -> !unique.add(e.getName()));
    

    注意,Person 类需要有一个 getter 来返回人名。

    【讨论】:

      【解决方案2】:

      覆盖hashCode()equals()。然后你可以使用这个:

      List<Person> collect = list.stream().distinct().collect(Collectors.toList());
      

      【讨论】:

      • distinct here 将应用于对象,而不是名称本身..
      • 这可能就是为什么他建议用相应的逻辑覆盖equalshashCode(如果他们有相同的名字,两个人是相等的)。
      • 是的,但这是一个非常糟糕的做法。仅基于单个属性说一个对象等于另一个对象,而不是其他对象是仅针对特定场景的糟糕设计。
      【解决方案3】:

      将列表变成一个map,其中key是Person::getName,value是对象本身,如果相等则选择第一个,然后得到一个Collection的map值,最后转换为一个列表

      list = list.stream().collect(Collectors.toMap(Person:getName, Function.Identity(), 
      (a, b) -> a)).values().stream().collect(Collections.toList());
      

      【讨论】:

      • 这将是地图,您不是在寻找列表作为结果吗?
      • 看到最后被收集到一个列表中
      【解决方案4】:

      这可以使用Comparator 轻松完成。因为这使用起来非常灵活,并且还允许根据您的需要进行多个比较标准。请参阅下面的代码:-

          Set<Person> expectedOutput = new TreeSet<>((person1, person2) ->
                  person1.getName().equals(person2.getName()) ? 0 : 1
          );
          list.listIterator().forEachRemaining(expectedOutput::add);
      

      我个人会避免为波动的标准覆盖等于。例如,如果我说如果在一种情况下名称相等,我的对象是相等的,而在另一种情况下,我说如果年龄相等,我的对象是相等的。那么最好使用comparator

      【讨论】:

        猜你喜欢
        • 2021-07-26
        • 2020-04-04
        • 1970-01-01
        • 1970-01-01
        • 2014-09-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-15
        相关资源
        最近更新 更多