【问题标题】:Troubles modifying a set with multiple iterators使用多个迭代器修改集合的麻烦
【发布时间】:2014-02-25 17:47:40
【问题描述】:

我想比较一个集合中的元素,以便合并过于相似的元素。为了赢得一些时间,我想在迭代过程中消除相似之处。 以下是我如何尝试继续:

Iterator<Personne> i1 = personnes.iterator();
while (i1.hasNext()) {
     Personne personneObservee = i1.next();
     Set<Personne> tmp = new HashSet<Personne>();
     tmp.addAll(personnes);
     Iterator<Personne> i2 = tmp.iterator();
     while (i2.hasNext()) {
        Personne autrePersonne = i2.next();
        if (personneObservee.isSimilarTo(autrePersonne)) {
            personnes.remove(autrePersonne);
        }
    }
    result.add(personneObservee.toString());
}

正如你可以从我的存在中猜到的那样,它不起作用,给了我这个不错的堆栈跟踪:

java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
        at java.util.HashMap$KeyIterator.next(HashMap.java:960)
        at NameDetectorWithBenefits.mergeSamePersons(NameDetectorWithBenefits.java:41)
        at App.main(App.java:71)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:297)
        at java.lang.Thread.run(Thread.java:744)

起初,我以为 i1 和 i2 正在迭代同一个集合,我会找到答案 here。因此,我每次都创建一个临时集。但是,它并没有解决问题。

有什么想法可能会出现问题吗?

【问题讨论】:

  • 您的isSimilarTo(Personne)equals(Object) 中的代码有何不同?
  • 它对不同的属性进行了一些计算,但只读取信息。

标签: java iterator


【解决方案1】:

在遍历集合时,使用迭代器从集合中删除元素,而不是使用 set.remove()

// wrong way
personnes.remove(autrePersonne); 

//correct way
it.remove(); 

【讨论】:

  • 它消除了异常,谢谢!明天我会检查它是否按预期工作。
【解决方案2】:

使用Iterator#remove() 而不是Set#remove(Object)

所以替换下面这行

personnes.remove(autrePersonne);

i2.remove();

更多详情请见here

【讨论】:

  • 虽然这是正确的,但你如何将它应用到他的具体例子中?
  • It#removeIt.remove 之间有区别还是只是约定?
  • @fxm Iterator#remove() 只是指Iterator 类的remove() 方法。在您的代码中,您将在 Iterator 对象(即 12.remove())上调用该方法
【解决方案3】:

当另一个线程正在迭代它时,您无法更新SET,因为出现ConcurrentModificationException 异常。

您正在迭代 SET

Iterator&lt;Personne&gt; i1 = personnes.iterator(); 并使用personnes.remove(autrePersonne); 删除元素。

使用Iterator remove方法移除元素

【讨论】:

  • 但是你不能在迭代时更新父 SET。还有你想要的输出是什么?
  • 包含不相似元素的集合。
  • 你正在使用 set 所以它不会包含类似的条目
  • 嗯,我的方式很相似,不是严格相等(因此是 isSimilar 函数)。
  • 什么是SimilarTo 方法的作用/
【解决方案4】:

分两步完成:

  1. 隔离需要删除的内容
  2. 移除

.

final Set<Personne> toRemove = new HashSet<>();
for (final Personne personne: personnes) {
    for (final Personne autrePersonne: personnes) {
        if (person.isSimilarTo(autrePersonne)) {
            toRemove.add(autrePersonne);
        }
    }
}
personnes.removeAll(toRemove);

另外,你需要注意autrePersonne等于personne的情况

【讨论】:

  • 虽然它可能有效,但就复杂性而言,它比我想要实现的成本更高。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 2023-03-24
相关资源
最近更新 更多