迭代列表并添加到列表,而不会引发 ConcurrentModificationException - Java

发布于 2025-01-11 10:35:14 字数 2483 浏览 0 评论 0原文

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

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

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

因此,我提出了以下解决方案来防止“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;
    }
}

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

Person1 名字 = Bob

Person2 名字 = Jan

Person3 名字 = Bob

Person4 FirstName = Ann

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

addPerson(Person1);

addPerson(Person2);

addPerson(Person3);

添加人员(人员4);

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

The Person Bob is already Entered in the list

Jan

Ann

Bob

Bob

我期望得到以下结果:

The Person Bob is already present

Jan

Ann

Bob

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

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

在迭代期间向集合添加元素

Apologies, this has been done to death but I am really struggling to implement a solution to this problem and I am quite new to Java.

I need to be able to call a method which basically allows a Person object to be added to a list.

The main problem I have encountered whilst trying to implement a solution is a 'ConcurrentModificationException' which is understandable given I have been trying to update the list whilst in the middle of a for each loop.

So, I have come up with the following solution which prevents the 'ConcurrentModificationException' but my solution doesn't work properly and seems overcomplicated - see following code snippet of method:

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;
    }
}

So, if for example I call the above addPerson method 4 separate times with a mixture of unique and duplicate objects (aPerson param), the method correctly identifies that there is already an object with the same first name in there but the persons list always seems to end up with a duplicate object (first name) in there e.g. if I have the following objects:

Person1
FirstName = Bob

Person2
FirstName = Jan

Person3
FirsName = Bob

Person4
FirstName = Ann

Then I make the following method call 4 separate times:

addPerson(Person1);

addPerson(Person2);

addPerson(Person3);

addPerson(Person4);

When I call a print method, I get the following output:

The Person Bob is already entered in the list

Jan

Ann

Bob

Bob

I would expect the following:

The Person Bob is already present

Jan

Ann

Bob

Apologies for all the waffle and what is probably a really simple solution to most of you but I have been stuck on this for a couple of days.

Similar article can be found here but I am still struggling.

Adding elements to a collection during iteration

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七色彩虹 2025-01-18 10:35:15

无需过多更改代码:

  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 来加速包含检查;也只是使用 anyMatch on persons 会带来更优雅的解决方案。

重复是由 for 循环及其 else 条件引起的。如果 BobJan 在您的集合中,并且您添加了第二个 Bob,则 Jan 将不等于Bob 和您的 else 路径被执行,将副本添加到您的最终 persons List 中。

Without changing your code too much:

  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);
  }

This would exit the method when a match is found, if there are no matches the person is simply added after the loop. Note the return in the first check.

Optimizations of this code could be using a Map or Set to speed up the contains check; also just using anyMatch on persons would lead to a more elegant solution.

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.

⊕婉儿 2025-01-18 10:35:15

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

You can use Set instead of list which will satisfy your need and implement the comparator or comparable interface for person comparison

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文