遍历列表并添加到列表而不会引发 ConcurrentModificationException - Java

Iterate through list and add to list without incurring ConcurrentModificationException - Java

抱歉,这已经死了,但我真的很难实施这个问题的解决方案,而且我对 Java 还很陌生。

我需要能够调用基本上允许将 Person 对象添加到列表中的方法。

我在尝试实施解决方案时遇到的主要问题是 'ConcurrentModificationException' 这是可以理解的,因为我一直在 for each 循环的中间尝试更新列表。

因此,我提出了以下解决方案来防止 'ConcurrentModificationException' 但我的解决方案无法正常工作并且看起来过于复杂 - 请参阅以下方法代码片段:

public void addPerson(Person aPerson) {
    // tempPersons list for temporarily storing Person objects
    tempPersons = new ArrayList<>();

    // if persons list is initially empty, add aPerson object to it
    if (persons.isEmpty()) {
        persons.add(aPerson);
    }
    // if persons list is not initially empty
    if (!persons.isEmpty()) {
        // loop through persons list
        for (Person anotherPerson : persons) {
            // if persons list anotherPerson first name is the same as the aPerson first name, print message
            if (anotherPerson.getFirstName().equals(aPerson.getFirstName())) {
                System.out.println("The Person " + aPerson.getFirstName() +
                        " is already entered in the list");
            }
            // otherwise add the aPerson object to the tempPersons list
            else {
                tempPersons.add(aPerson);
            }
        }
        // once out of loop, add the tempPersons list to the persons list
        persons.addAll(tempPersons);
        // create new tempPersons2 list based on a hashset of the persons list so there are no duplicates
        List<Person> tempPersons2 = new ArrayList<>(
                new HashSet<>(persons));
        // assign tempPersons2 list without duplicates to persons list
        persons = tempPersons2;
    }
}

因此,例如,如果我使用唯一和重复对象(aPerson 参数)的混合分别调用上述 addPerson 方法 4 次,该方法正确地识别出其中已经有一个具有相同名字的对象,但是人员列表似乎总是以重复的对象(名字)结尾,例如如果我有以下对象:

人1 名字 = 鲍勃

人2 名字 = 简

人 3 名字 = 鲍勃

人4 名字 = 安

然后我分别调用以下方法 4 次:

addPerson(Person1);

addPerson(Person2);

addPerson(Person3);

addPerson(Person4);

当我调用打印方法时,我得到以下输出:

Bob 已输入列表

一月

鲍勃

鲍勃

我希望得到以下结果:

Bob 已经存在

一月

鲍勃

为所有华夫饼道歉,这对你们大多数人来说可能是一个非常简单的解决方案,但我已经坚持了几天。

可以在这里找到类似的文章,但我仍在努力。

Adding elements to a collection during iteration

您可以使用 Set 而不是 list,这将满足您的需要并实现比较器或可比较接口以进行人员比较

无需过多更改代码:

  public void addPerson(Person person) {
    // The guard is more or less a premature optimization and should be removed.
    if (persons.isEmpty()) {
      persons.add(person);
      return;
    }

    for (Person anotherPerson : persons) {
      if (anotherPerson.getFirstName().equals(person.getFirstName())) {
        System.out.println("The Person " + person.getFirstName() +
            " is already entered in the list");
        return;
      }
    }
    persons.add(person);
  }

这将在找到匹配项时退出该方法,如果没有匹配项,则只需在循环后添加 person。注意第一次检查中的return

此代码的优化可以使用 MapSet 来加速包含检查;在 persons 上使用 anyMatch 也会导致更优雅的解决方案。

The duplicates are caused by your for loop and it's else condition. If Bob and Jan is in your collection and you add a second Bob then Jan won't be equal to Bob and your else path is executed adding a duplicate to your final persons List.