]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix for #4536 - ListSet.set() removes elements from itemSet even if they are still...
authorArtur Signell <artur.signell@itmill.com>
Thu, 15 Apr 2010 11:25:18 +0000 (11:25 +0000)
committerArtur Signell <artur.signell@itmill.com>
Thu, 15 Apr 2010 11:25:18 +0000 (11:25 +0000)
svn changeset:12559/svn branch:6.3

src/com/vaadin/data/util/ListSet.java

index 0a3d954a3e88087298541177b1e8a0a19ffaee9d..30045eba1175c9cf390f93daf04bb04afb8402e0 100644 (file)
@@ -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<E> extends ArrayList<E> {
     private HashSet<E> 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<E, Integer> duplicates = new HashMap<E, Integer>();
+
     public ListSet() {
         super();
         itemSet = new HashSet<E>();
@@ -35,7 +42,7 @@ public class ListSet<E> extends ArrayList<E> {
         itemSet = new HashSet<E>(initialCapacity);
     }
 
-    // Delegate contains operations to the set\r
+    // Delegate contains operations to the set
     @Override
     public boolean contains(Object o) {
         return itemSet.contains(o);
@@ -46,11 +53,11 @@ public class ListSet<E> extends ArrayList<E> {
         return itemSet.containsAll(c);
     }
 
-    // Methods for updating the set when the list is updated.\r
+    // Methods for updating the set when the list is updated.
     @Override
     public boolean add(E e) {
         if (contains(e)) {
-            // Duplicates are not allowed\r
+            // Duplicates are not allowed
             return false;
         }
 
@@ -69,7 +76,7 @@ public class ListSet<E> extends ArrayList<E> {
     @Override
     public void add(int index, E element) {
         if (contains(element)) {
-            // Duplicates are not allowed\r
+            // Duplicates are not allowed
             return;
         }
 
@@ -173,15 +180,50 @@ public class ListSet<E> extends ArrayList<E> {
     @Override
     public E set(int index, E element) {
         if (contains(element)) {
-            // Element already exist in the list\r
+            // Element already exist in the list
             if (get(index) == element) {
-                // At the same position, nothing to be done\r
+                // 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;