【问题标题】:finding duplicates using java 8 [duplicate]使用java 8查找重复项[重复]
【发布时间】:2019-10-23 23:40:28
【问题描述】:

我有一个包含 id、name 和 address 字段的员工类。如果两个员工的 id 和 name 完全相同,则认为他们是相同的。现在我有一个员工列表,现在我的任务是获取重复员工的集合。

这是我的 Employee 类代码,其中包含基于 id 和 name 字段覆盖的 hascode 和 equals 方法。

class Employee {
    int id;
    String name;
    String address;

    public Employee(int id, String name, String address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", address=" + address + "]";
    }


    // auto generated by eclipse based on fields for id and name    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

现在我有了这个代码来查找重复的员工

public static void main(String[] args) {
    Employee e1 = new Employee(1, "John", "SFO");
    Employee e2 = new Employee(2, "Doe", "NY");
    Employee e3 = new Employee(1, "John", "NJ");

    List<Employee> list = Arrays.asList(e1, e2, e3);

    Set<Employee> set = new HashSet<>();
    for (int i = 0; i < list.size(); i++) {
        for (int j = i + 1; j < list.size(); j++) {
            if (list.get(i).equals(list.get(j))) {
                set.add(list.get(i));
            }
        }
    }

    System.out.println(set);
}

此代码运行良好,并在我的集合中为我提供了 id 为 1 的员工。

如何使用 Java 8 lamda 和流来执行相同的操作? flatmap 在这种情况下有用吗?

【问题讨论】:

  • 您可以使用以下代码 System.out.println(list.stream().filter(em -&gt; list.indexOf(em) &gt; -1 &amp;&amp; list.get(list.indexOf(em)) != em).collect(Collectors.toSet())); 对嵌套循环执行相同的逻辑
  • 这里的预期结果是什么? new Employee(1, "John", "SFO")new Employee(1, "John", "NJ") 两者都被视为彼此重复。您想获得 both 还是只获得 one (在这种情况下,您要选择哪个标准)? IMO 获得重复意味着收集 所有 可以被视为相等的单独元素。
  • 或者,您可能只想获得每个“员工类别”中的一个代表,而不管它是该类别中的哪一个?
  • java.util.HashSet 不存在这个原因吗?

标签: java java-8


【解决方案1】:

如果您的要求有点具体,在大多数情况下并没有真正的帮助。我会这样做:

final Map<Employee, Long> groupedWithCount = employees.stream()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

现在您拥有所需的所有信息以及更多信息。员工在此地图中按人数分组,您的数据如下所示:

{
  Employee [id=2, name=Doe, address=NY] = 1,
  Employee [id=1, name=John, address=SFO] = 2
}

显然,重复项是值 > 1 的条目。

【讨论】:

  • 值得一提的是,这将只从一组平等的员工中收集一名代表,他们将被视为关键。如果我们想获得该组,我们可以改用Collectors.groupingBy(Function.identity()) 并获得Map&lt;Employee, List&lt;Employee&gt;&gt;,其中每个List&lt;Employee&gt; 将拥有所有“平等”的员工。
【解决方案2】:

另一种方法:

list.stream()
    .collect(groupingBy(identity(), counting()))        
    .entrySet()
    .stream()
    .filter(e -> e.getValue() != 1)
    .map(Map.Entry::getKey)
    .collect(toList());

或:

list.stream()
    .collect(groupingBy(identity()))        
    .values()
    .stream()
    .filter(l -> l.size() != 1)
    .map(l -> l.get(0))                 // The list cannot be empty
    .collect(toList());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 2011-04-26
    • 2022-01-02
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多