From: Artur Signell Date: Tue, 2 Mar 2010 13:57:28 +0000 (+0000) Subject: ListSet implementation for #4106 - BeanItemContainer slow in some instances X-Git-Tag: 6.7.0.beta1~2000 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b4a62c4b8f69cd8f1c15d5983821b51ebc428235;p=vaadin-framework.git ListSet implementation for #4106 - BeanItemContainer slow in some instances svn changeset:11593/svn branch:6.3 --- diff --git a/src/com/vaadin/data/util/ListSet.java b/src/com/vaadin/data/util/ListSet.java new file mode 100644 index 0000000000..8dc8c6bbfd --- /dev/null +++ b/src/com/vaadin/data/util/ListSet.java @@ -0,0 +1,198 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +/** + * ListSet is an internal Vaadin class which implements a combination of a List + * and a Set. The main purpose of this class is to provide a fast + * {@link #contains(Object)} method. Each inserted object must by unique (as + * specified by {@link #equals(Object)}). + * + * This class is subject to change and should not be used outside Vaadin core. + */ +public class ListSet extends ArrayList { + private HashSet itemSet = null; + + public ListSet() { + super(); + itemSet = new HashSet(); + } + + public ListSet(Collection c) { + super(c); + itemSet = new HashSet(c.size()); + itemSet.addAll(c); + } + + public ListSet(int initialCapacity) { + super(initialCapacity); + itemSet = new HashSet(initialCapacity); + } + + // Delegate contains operations to the set + @Override + public boolean contains(Object o) { + return itemSet.contains(o); + } + + @Override + public boolean containsAll(Collection c) { + return itemSet.containsAll(c); + } + + // Methods for updating the set when the list is updated. + @Override + public boolean add(E e) { + if (contains(e)) { + // Duplicates are not allowed + return false; + } + + if (super.add(e)) { + itemSet.add(e); + return true; + } else { + return false; + } + }; + + /** + * Works as java.util.ArrayList#add(int, java.lang.Object) but returns + * immediately if the element is already in the ListSet. + */ + @Override + public void add(int index, E element) { + if (contains(element)) { + // Duplicates are not allowed + return; + } + + super.add(index, element); + itemSet.add(element); + } + + @Override + public boolean addAll(Collection c) { + boolean modified = false; + Iterator i = c.iterator(); + while (i.hasNext()) { + E e = i.next(); + if (contains(e)) { + continue; + } + + if (add(e)) { + itemSet.add(e); + modified = true; + } + } + return modified; + } + + @Override + public boolean addAll(int index, Collection c) { + ensureCapacity(size() + c.size()); + + boolean modified = false; + Iterator i = c.iterator(); + while (i.hasNext()) { + E e = i.next(); + if (contains(e)) { + continue; + } + + add(index++, e); + itemSet.add(e); + modified = true; + } + + return modified; + } + + @Override + public void clear() { + super.clear(); + itemSet.clear(); + } + + @Override + public int indexOf(Object o) { + if (!contains(o)) { + return -1; + } + + return super.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + if (!contains(o)) { + return -1; + } + + return super.lastIndexOf(o); + } + + @Override + public E remove(int index) { + E e = super.remove(index); + + if (e != null) { + itemSet.remove(e); + } + + return e; + } + + @Override + public boolean remove(Object o) { + if (super.remove(o)) { + itemSet.remove(o); + return true; + } else { + return false; + } + } + + @Override + protected void removeRange(int fromIndex, int toIndex) { + HashSet toRemove = new HashSet(); + for (int idx = fromIndex; idx < toIndex; idx++) { + toRemove.add(get(idx)); + } + super.removeRange(fromIndex, toIndex); + itemSet.removeAll(toRemove); + } + + @Override + public E set(int index, E element) { + if (contains(element)) { + // Element already exist in the list + if (get(index) == element) { + // At the same position, nothing to be done + return element; + } else { + // At another position, cannot set + return null; + } + } + + E old = super.set(index, element); + itemSet.remove(old); + itemSet.add(element); + + return old; + } + + @SuppressWarnings("unchecked") + @Override + public Object clone() { + ListSet v = (ListSet) super.clone(); + v.itemSet = new HashSet(itemSet); + return v; + } + +}