From: Artur Signell Date: Thu, 15 Apr 2010 11:25:18 +0000 (+0000) Subject: Fix for #4536 - ListSet.set() removes elements from itemSet even if they are still... X-Git-Tag: 6.7.0.beta1~1711^2~20 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=45b8f0c0a010f4156e6e2b10288efd7921e020e4;p=vaadin-framework.git Fix for #4536 - ListSet.set() removes elements from itemSet even if they are still contained in list svn changeset:12559/svn branch:6.3 --- diff --git a/src/com/vaadin/data/util/ListSet.java b/src/com/vaadin/data/util/ListSet.java index 0a3d954a3e..30045eba11 100644 --- a/src/com/vaadin/data/util/ListSet.java +++ b/src/com/vaadin/data/util/ListSet.java @@ -5,6 +5,7 @@ package com.vaadin.data.util; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -19,6 +20,12 @@ import java.util.Iterator; public class ListSet extends ArrayList { private HashSet itemSet = null; + /** + * Contains a map from an element to the number of duplicates it has. Used + * to temporarily allow duplicates in the list. + */ + private HashMap duplicates = new HashMap(); + public ListSet() { super(); itemSet = new HashSet(); @@ -35,7 +42,7 @@ public class ListSet extends ArrayList { itemSet = new HashSet(initialCapacity); } - // Delegate contains operations to the set + // Delegate contains operations to the set @Override public boolean contains(Object o) { return itemSet.contains(o); @@ -46,11 +53,11 @@ public class ListSet extends ArrayList { return itemSet.containsAll(c); } - // Methods for updating the set when the list is updated. + // Methods for updating the set when the list is updated. @Override public boolean add(E e) { if (contains(e)) { - // Duplicates are not allowed + // Duplicates are not allowed return false; } @@ -69,7 +76,7 @@ public class ListSet extends ArrayList { @Override public void add(int index, E element) { if (contains(element)) { - // Duplicates are not allowed + // Duplicates are not allowed return; } @@ -173,15 +180,50 @@ public class ListSet extends ArrayList { @Override public E set(int index, E element) { if (contains(element)) { - // Element already exist in the list + // Element already exist in the list if (get(index) == element) { - // At the same position, nothing to be done + // At the same position, nothing to be done return element; + } else { + // Adding at another position. We assume this is a sort + // operation and temporarily allow it. + + // We could just remove (null) the old element and keep the list + // unique. This would require finding the index of the old + // element (indexOf(element)) which is not a fast operation in a + // list. So we instead allow duplicates temporarily. + + Integer nr = duplicates.get(element); + if (nr == null) { + nr = 1; + } else { + nr++; + } + + // Store the number of duplicates of this element so we know + // later on if we should remove an element from the set or if it + // was a duplicate (see below). + duplicates.put(element, nr); } } E old = super.set(index, element); - itemSet.remove(old); + Integer dupl = duplicates.get(old); + if (dupl != null) { + // A duplicate was present so we only decrement the duplicate count + // and continue + if (dupl == 1) { + // This is what always should happen. A sort swaps two items and + // temporarily breaks the uniqueness and then restore it + // immediately afterwards. + duplicates.remove(old); + } else { + duplicates.put(old, dupl - 1); + } + } else { + // The "old" value is no longer in the list. + itemSet.remove(old); + } itemSet.add(element); return old;