【问题标题】:Get duplicated items with specific format from Java Stream从 Java Stream 获取具有特定格式的重复项
【发布时间】:2019-12-04 10:43:01
【问题描述】:

我是 Java 流的新手,我现在正在玩它们。鉴于我收到了一份人员列表,我想检测其中哪些人重复并将其打印为“{Id1} 与 {Id3}{Id4} 重复,其重复值为姓名、姓氏、家庭名和生日”

所以这是我的 person 类,我已经重写了 equals 方法,以便根据我的标准获得重复项

public class Person {

private int id;
private String name;
private String familyName;
private String birthday;
private String city;

public Person(int id, String name, String familyName, String birthday, String city) {
    this.id = id;
    this.name = name;
    this.familyName = familyName;
    this.birthday = birthday;
    this.city = city;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getFamilyName() {
    return familyName;
}

public void setFamilyName(String familyName) {
    this.familyName = familyName;
}

public String getBirthday() {
    return birthday;
}

public void setBirthday(String birthday) {
    this.birthday = birthday;
}

public String getCity() {
    return city;
}

public void setCity(String city) {
    this.city = city;
}

 @Override
public int hashCode() {
    return Objects.hash( name,familyName,birthday,city);
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return false;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Person other = (Person) obj;
    if (!Objects.equals(name, other.name)) {
        return false;
    }
    if (!Objects.equals(familyName, other.familyName)) {
        return false;
    }

    if (!Objects.equals(birthday, other.birthday)) {
        return false;
    }
   return true;
}

}

然后,我通过以下方法获取重复列表

personList.stream()
            .filter(p -> personList.contains(p))
            .collect(Collectors.toList()).forEach(p-> {
                System.out.println(p.getId() + " " + p.getName() + " " + p.getFamilyName() + " " + p.getBirthday());
            });

它打印以下内容:

  • 2 安德烈斯·冈萨雷斯 12/4/1990
  • 4 莫琳·佩雷斯 15/07/92
  • 7 安德烈斯·冈萨雷斯 1990 年 12 月 4 日
  • 9 莫琳·佩雷斯 15/07/92
  • 11 莫琳佩雷斯 15/07/92

如您所见,ID 的 2 和 7 是重复的,4,9 和 11 也是重复的,这些是我需要以该格式打印的那些,但我不知道如何使用流来做到这一点.

【问题讨论】:

  • personList.stream().filter(p -> personList.contains(p)) 最好执行forEach,因为p 始终包含在personList 中。

标签: java list java-stream


【解决方案1】:

首先,您应该修复您的hashCode() 实现以匹配您的equals。如果两个对象相等,则它们必须具有相同的hashCode()

现在,您的Stream 管道返回所有元素,因为您的filterPredicate 将始终返回true

相反,您可以将List 的相等元素分组:

Map<Person,List<Integer>> grouped =
    personList.stream()
              .collect(Collectors.groupingBy(Function.identity(),
                                             Collectors.mapping(Person::getId,
                                                                Collectors.toList())));

现在,对于每个 Person,您都有一个关联的标识符 List。 您可以迭代此 Map 并打印具有大小 > 1 的 Lists 的 Persons。

例如:

personList.stream()
          .collect(Collectors.groupingBy(Function.identity(),
                                         Collectors.mapping(Person::getId,
                                                            Collectors.toList())));
          .entrySet()
          .stream()
          .filter(e -> e.getValue().size() > 1)
          .forEach(e -> System.out.println(e.getKey().getId() + " " + e.getKey().getName() + " " + e.getKey().getFamilyName() + " " + e.getKey().getBirthday() + " " + e.getValue()));

【讨论】:

  • 感谢您的回答我已经更新了哈希码方法以包含每个字段。我正在尝试使用您的代码,但它现在没有打印任何内容我会看看并尝试看看发生了什么。再次感谢
  • @axcha15 如果两个具有不同 ID 的人不能彼此相等,则不应在 hashCode() 中包含 id 属性。
  • 知道了,它成功了,这是我第一次覆盖哈希码,所以不知道这种行为。这是更新哈​​希码方法后的输出 4 Maureen Perez 15/07/92 [4, 9, 11] 2 Andres Gonzalez 12/4/1990 [2, 7]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
  • 2018-05-09
  • 2018-11-14
  • 1970-01-01
  • 2019-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多