【问题标题】:ArrayList of objects, compare objects and find duplicates, add object to new ArrayList only once for each duplicate对象的 ArrayList,比较对象并查找重复项,每个重复项仅将对象添加到新的 ArrayList 一次
【发布时间】:2017-12-15 12:58:39
【问题描述】:

我已经弄清楚如何比较两个 ArrayList 并将重复项添加到新的 ArrayList 中。

    ArrayList<Student> allStudentsA = assignStudents();
    ArrayList<Student> allStudentsB = allStudentsA;

    for (Student studentA : allStudentsA) {
        for (Student studentB : allStudentsB) {
            if (studentA.getId().equals(studentB.getId()) && studentA.getEduNumber() != studentB.getEduNumber()) {
                duplicateStudents.add(studentB);
            }
        }
    }

不管我怎么做,我每次都添加每个副本一次。由于“Rodaba”出现了 7 次,因为她有 7 个不同的优先级,因此她被添加到列表中 7*6 次。这是我打印出来的方式:

    for (Student student : duplicateStudents) {
        if (student.getFornavn().equals("Rodaba")) {
            System.out.println("Name: " + student.getFornavn() + "\t \t" + "EduNumber: " + student.getOptagelsesområde() + "\t" + "Prio: " + student.getPrio());
        }
    }

有没有一种聪明的方法可以避免这种情况,并且只为她申请的每个优先级添加一次“Rodaba”? 这是我的输出,有没有办法只获取标记的部分?

我已经被这个问题困扰了很长时间。对于制作 ArrayList 的更好方法以及如何解决这个问题的建议,我真的很感激。

【问题讨论】:

  • 我认为使用Map 可能是一个很好的解决方案。它还消除了嵌套的for 循环。
  • 为什么不检查学生是否已经在列表中?此外,它与此无关,但您可以覆盖您的 Student#toString 方法以更干净地打印它
  • @Nathan 问题在于学生将在列表中 n 次,其中 n 是他们拥有的优先级数量。
  • @RohitMourya 你能详细说明一下吗?
  • @LarsChristensen 然后,只需检查它是否存在于具有相同优先级的列表中。

标签: java arraylist duplicates compare


【解决方案1】:

正如我在 cmets 中指出的,您可以在添加之前简单地检查一个学生是否存在:

ArrayList<Student> allStudentsA = assignStudents();
ArrayList<Student> allStudentsB = allStudentsA;

for (Student studentA : allStudentsA)
    for (Student studentB : allStudentsB)
        if (studentA.getId().equals(studentB.getId())
            && studentA.getEduNumber() != studentB.getEduNumber())
            if (!duplicateStudents.contains(studentB))
                duplicateStudents.add(studentB);

请注意,这只有在您覆盖了Student 类的equalshashCode 方法时才有效,因为对象没有相同的引用。

基本上,您将在添加之前检查Student 是否已经在列表中。如果您正确实施了 equals 方法,学生 A 将不等于具有不同优先级的 A

【讨论】:

  • 同样的问题是,当它遇到第一个学生时,它会停止添加。所以它只在第 25 个优先级添加一次“Rodaba”,而我想要为每个优先级添加一次。
  • @LarsChristensen 然后它依赖于您的 Student#equals 实现:即使优先级不同,您的 equals 方法似乎也会返回 true。
  • 你是神 Nathan,这就是问题所在。我编辑了我的 equals 方法来正确检查优先级,问题就解决了。
  • @LarsChristensen 很高兴我能帮上忙,但我不能接受上帝的部分——这个荣誉归于Jon Skeet, SO's Chuck Norris:D
【解决方案2】:

您可以对流使用不同的方法。例如:

List<Student> allStudentsA = assignStudents();
List<Student> duplicateStudents = allStudents.stream()
    .collect(groupingBy(Student::getId)) 
//Now you've got Map<String, List<Student>> (assuming id is of type String).
//Id of an user is a key. In value (list) you have all Students with the same id.
//Now we want to take this lists which have size greater than two and merge them.
    .values()
    .stream()
    .filter(list -> list.size() >= 2)
    .flatMap(List::stream)
    .collect(Collectors.toList());

(欢迎改进。)

【讨论】:

  • 感谢您提供替代方法。
猜你喜欢
  • 2016-08-10
  • 2016-10-31
  • 2016-01-05
  • 1970-01-01
  • 2012-12-20
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多