从列表中删除(并计算)重复项

remove (and count) duplicates from a list

是否可以在同一列表的两个迭代器之间进行迭代并删除嵌套迭代器中的一项

版本 1(不起作用):

var i = all.iterator();
while (i.hasNext()) {
    var a = i.next();
    var j = all.iterator();
    while (j.hasNext()) {
        var b = j.next();
        if (!a.shouldBRemoved(b)) {
            a.setDuplicates(a.getDuplicates + 1);
            // I want to remove the element on the fly 
            // because on each iteration the iterated elements will have a decreased size and will iterate faster (because of fewer elements)
            // However: this does NOT work because of ConcurrentModificationException:
            j.remove();  
        }
    }

}

我得到一个 java.util.ConcurrentModificationException,因为我在同一个迭代器中修改了一个元素..

我可以通过使用另一个列表 removableItems 并将这些项目放入其中来解决这个问题:

版本 2(有效):

for (var a : all) {
    for (var b : all) {
        if (!a.shouldBRemoved(b)) {
            a.setDuplicates(a.getDuplicates + 1);
            // this works, 
            // however I must use an additation list to keep track of the items to be removed
            // it's also not more performant than removing the elements on the fly 
            // because on each iteration the iterated elements has the same size
            removableItems.add(b);
        }
    }
}
all.removeAll(removableItems);
    

有没有办法解决这个问题而不需要中间列表removableItems我想删除元素苍蝇。

尝试使用支持并发修改的CopyOnWriteArrayList

List < String > myList = new CopyOnWriteArrayList < String > ();
    myList.add("1");
    myList.add("2");
    myList.add("3");
    myList.add("4");
    myList.add("5");
    for (int i = 0; i < myList.size(); i++) {
      System.out.println("List value: " + myList.get(i));
      if (myList.get(i).equals("3")) {
        myList.remove(i);
        i--;
        myList.add("6");
      }
    }
    System.out.println("List Size:" + myList.size());

到目前为止我找到了一个很好的解决方案(版本 3):

List<Item> removeDuplicates(List<Item> all) {
        var uniqueResults = new ArrayList<Item>();
        for (var a : all) {
            for (var b : all) {
                // check if "a" and "b" is not the same instance, but have equal content
                if (!a.equals(b) && a.isDeepEqualTo(b)) {
                    if (a.duplicates == 0 && b.duplicates == 0) {
                        // "a" has duplicates: 
                        // Add only "a" and discard "b" for the rest of the loops.
                        uniqueResults.add(a);
                    }
                    // count the number of duplicates
                    a.duplicates = a.duplicates + 1;
                }
            }
            // "a" has no duplicates, add it.
            if (a.duplicates == 0 && !uniqueResults.contains(a)) {
                uniqueResults.add(a);
            }
        }
        return uniqueResults;
}

它到目前为止有效 - 我没有看到任何边缘情况会错误地(不)删除。

它也比使用 版本 2(及其 removableItems()-列表)更好,因为它性能更高(尤其是对于大列表),因为我们不使用 removeremovAll,我们只添加项目(具有 O(1))。