Author: rwhitcomb Date: Mon Oct 30 17:14:55 2023 New Revision: 1913450 URL: http://svn.apache.org/viewvc?rev=1913450&view=rev Log: PIVOT-1032: Style and Javadoc changes to some of the collection classes.
Modified: pivot/trunk/core/src/org/apache/pivot/collections/ArrayAdapter.java pivot/trunk/core/src/org/apache/pivot/collections/ArrayList.java pivot/trunk/core/src/org/apache/pivot/collections/HashMap.java pivot/trunk/core/src/org/apache/pivot/collections/LinkedList.java Modified: pivot/trunk/core/src/org/apache/pivot/collections/ArrayAdapter.java URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/collections/ArrayAdapter.java?rev=1913450&r1=1913449&r2=1913450&view=diff ============================================================================== --- pivot/trunk/core/src/org/apache/pivot/collections/ArrayAdapter.java (original) +++ pivot/trunk/core/src/org/apache/pivot/collections/ArrayAdapter.java Mon Oct 30 17:14:55 2023 @@ -31,24 +31,30 @@ import org.apache.pivot.util.Utils; public class ArrayAdapter<T> extends ReadOnlySequence<T> implements Serializable { private static final long serialVersionUID = 1143706808122308239L; - private T[] array; + /** The underlying array we are wrapping with this adapter. */ + private T[] wrappedArray; + /** + * Wrap a Java array with this adapter. + * + * @param array Standard array of objects to be wrapped. + */ @SuppressWarnings({ "unchecked" }) public ArrayAdapter(final T... array) { Utils.checkNull(array, "array"); - this.array = array; + wrappedArray = array; } @Override public T get(final int index) { - return array[index]; + return wrappedArray[index]; } @Override public int indexOf(final T item) { - for (int index = 0; index < array.length; index++) { - if ((item == null && array[index] == null) || item.equals(array[index])) { + for (int index = 0; index < wrappedArray.length; index++) { + if ((item == null && wrappedArray[index] == null) || item.equals(wrappedArray[index])) { return index; } } @@ -58,6 +64,6 @@ public class ArrayAdapter<T> extends Rea @Override public int getLength() { - return array.length; + return wrappedArray.length; } } Modified: pivot/trunk/core/src/org/apache/pivot/collections/ArrayList.java URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/collections/ArrayList.java?rev=1913450&r1=1913449&r2=1913450&view=diff ============================================================================== --- pivot/trunk/core/src/org/apache/pivot/collections/ArrayList.java (original) +++ pivot/trunk/core/src/org/apache/pivot/collections/ArrayList.java Mon Oct 30 17:14:55 2023 @@ -41,22 +41,25 @@ public class ArrayList<T> implements Lis * Iterator through the items of the ArrayList. */ private class ArrayListItemIterator implements ItemIterator<T> { + /** Current index into the list for this iterator. */ private int index = 0; - private int modificationCountLocal; + /** Modification count for the list at the time this iterator was created; + * used to detect concurrent modifications to the list. + */ + private int iteratorModificationCount; + /** Current direction of iteration. */ private boolean forward = true; /** * Initialize the iterator. */ ArrayListItemIterator() { - modificationCountLocal = ArrayList.this.modificationCount; + iteratorModificationCount = ArrayList.this.modificationCount; } @Override public boolean hasNext() { - if (modificationCountLocal != ArrayList.this.modificationCount) { - throw new ConcurrentModificationException(); - } + checkConcurrentModification(); return (index < length); } @@ -73,9 +76,7 @@ public class ArrayList<T> implements Lis @Override public boolean hasPrevious() { - if (modificationCountLocal != ArrayList.this.modificationCount) { - throw new ConcurrentModificationException(); - } + checkConcurrentModification(); return (index > 0); } @@ -105,7 +106,7 @@ public class ArrayList<T> implements Lis indexBoundsCheck(); ArrayList.this.insert(item, index); - modificationCountLocal++; + iteratorModificationCount++; } @Override @@ -113,7 +114,7 @@ public class ArrayList<T> implements Lis indexBoundsCheck(); ArrayList.this.update(forward ? index - 1 : index, item); - modificationCountLocal++; + iteratorModificationCount++; } @Override @@ -125,7 +126,18 @@ public class ArrayList<T> implements Lis } ArrayList.this.remove(index, 1); - modificationCountLocal++; + iteratorModificationCount++; + } + + /** + * Check if the modification count saved at the beginning of our iteration + * is still the same as the main list. Throw the exception if not. + * @throws ConcurrentModificationException if the list was changed while iterating + */ + private void checkConcurrentModification() { + if (iteratorModificationCount != ArrayList.this.modificationCount) { + throw new ConcurrentModificationException(); + } } /** @@ -137,17 +149,51 @@ public class ArrayList<T> implements Lis } } + /** + * The internal array of items used to store the elements of this list. + */ private Object[] items; + + /** + * The current length of this list. + */ private int length = 0; + /** + * The comparator used for sorting the list (if any). + */ private Comparator<T> comparator = null; + /** + * Modification count - used to tell if concurrent modifications + * occur during iteration. + */ private transient int modificationCount = 0; + /** + * The listeners for changes to the list (which would include any components + * using this list as their data model). + */ private transient ListListenerList<T> listListeners = null; + /** + * Default initial capacity of this list if none is specified + * at construction. + */ public static final int DEFAULT_CAPACITY = 10; /** + * The desirable load factor (excess allocation at resize time). + */ + private static final float LOAD_FACTOR = 1.5f; + + /** + * The prime multiplier used in the {@link #hashCode} calculation to give + * nicely spaced values. + */ + private static final int HASH_MULTIPLIER = 31; + + + /** * Construct a new unsorted ArrayList with the default capacity. */ public ArrayList() { @@ -158,11 +204,11 @@ public class ArrayList<T> implements Lis * Construct a new ArrayList to be sorted by the given comparator, with the * default capacity. * - * @param comparator A comparator to sort the entries in the list. + * @param newComparator A comparator to sort the entries in the list. */ - public ArrayList(final Comparator<T> comparator) { + public ArrayList(final Comparator<T> newComparator) { this(); - this.comparator = comparator; + comparator = newComparator; } /** @@ -182,37 +228,37 @@ public class ArrayList<T> implements Lis * with the given capacity. * * @param capacity The initial capacity for this list. - * @param comparator The comparator to use when sorting the list. + * @param newComparator The comparator to use when sorting the list. */ - public ArrayList(final int capacity, final Comparator<T> comparator) { + public ArrayList(final int capacity, final Comparator<T> newComparator) { this(capacity); - this.comparator = comparator; + comparator = newComparator; } /** * Construct a new ArrayList with the given list of items. * - * @param items The initial list of values for the list. + * @param initialItems The initial list of values for the list. */ @SuppressWarnings("unchecked") - public ArrayList(final T... items) { - this(items, 0, items.length); + public ArrayList(final T... initialItems) { + this(initialItems, 0, initialItems.length); } /** * Construct a new ArrayList with a subset of the given list of items. * - * @param items The full array of items to choose from. + * @param initialItems The full array of items to choose from. * @param index The starting location of the items to choose. * @param count The count of items to pick from the full array, starting at the index. * @throws IndexOutOfBoundsException if the given index is negative or greater than the count. */ - public ArrayList(final T[] items, final int index, final int count) { - Utils.checkNull(items, "items"); - Utils.checkIndexBounds(index, count, 0, items.length); + public ArrayList(final T[] initialItems, final int index, final int count) { + Utils.checkNull(initialItems, "initial items"); + Utils.checkIndexBounds(index, count, 0, initialItems.length); - this.items = new Object[count]; - System.arraycopy(items, index, this.items, 0, count); + items = new Object[count]; + System.arraycopy(initialItems, index, items, 0, count); length = count; } @@ -220,28 +266,28 @@ public class ArrayList<T> implements Lis /** * Construct a new ArrayList with the given sequence of items. * - * @param items The initial list of values for the list. + * @param initialItems The initial list of values for the list. */ - public ArrayList(final Sequence<T> items) { - this(items, 0, items.getLength()); + public ArrayList(final Sequence<T> initialItems) { + this(initialItems, 0, initialItems.getLength()); } /** * Construct a new ArrayList with a subset of the given sequence of items. * - * @param items The full sequence of items to choose from. + * @param initialItems The full sequence of items to choose from. * @param index The starting location of the items to choose. * @param count The count of items to pick from the full sequence, starting at the index. * @throws IndexOutOfBoundsException if the given index is negative or greater than the count. */ - public ArrayList(final Sequence<T> items, final int index, final int count) { - Utils.checkNull(items, "items"); - Utils.checkIndexBounds(index, count, 0, items.getLength()); + public ArrayList(final Sequence<T> initialItems, final int index, final int count) { + Utils.checkNull(initialItems, "initial items"); + Utils.checkIndexBounds(index, count, 0, initialItems.getLength()); - this.items = new Object[count]; + items = new Object[count]; for (int i = 0; i < count; i++) { - this.items[i] = items.get(index + i); + items[i] = initialItems.get(index + i); } length = count; @@ -250,30 +296,30 @@ public class ArrayList<T> implements Lis /** * Copy the given ArrayList into a new one. * - * @param arrayList The existing list to copy into this one. + * @param list The existing list to copy into this one. */ - public ArrayList(final ArrayList<T> arrayList) { - this(arrayList, 0, arrayList.length); + public ArrayList(final ArrayList<T> list) { + this(list, 0, list.length); } /** * Construct a new ArrayList with a subset of the given ArrayList. * - * @param arrayList The full list of items to choose from. + * @param list The full list of items to choose from. * @param index The starting location of the items to choose. * @param count The count of items to pick from the full list, starting at the index. * @throws IndexOutOfBoundsException if the given index is negative or greater than the count. */ - public ArrayList(final ArrayList<T> arrayList, final int index, final int count) { - Utils.checkNull(arrayList, "arrayList"); - Utils.checkIndexBounds(index, count, 0, arrayList.length); + public ArrayList(final ArrayList<T> list, final int index, final int count) { + Utils.checkNull(list, "list"); + Utils.checkIndexBounds(index, count, 0, list.length); items = new Object[count]; length = count; - System.arraycopy(arrayList.items, index, items, 0, count); + System.arraycopy(list.items, index, items, 0, count); - comparator = arrayList.comparator; + comparator = list.comparator; } /** @@ -289,7 +335,7 @@ public class ArrayList<T> implements Lis } @Override - public int add(final T item) { + public final int add(final T item) { int index = -1; if (comparator == null) { @@ -309,7 +355,7 @@ public class ArrayList<T> implements Lis } @Override - public void insert(final T item, final int index) { + public final void insert(final T item, final int index) { insert(item, index, true); } @@ -355,7 +401,7 @@ public class ArrayList<T> implements Lis @SuppressWarnings("unchecked") @Override - public T update(final int index, final T item) { + public final T update(final int index, final T item) { Utils.checkIndexBounds(index, 0, length - 1); T previousItem = (T) items[index]; @@ -387,7 +433,7 @@ public class ArrayList<T> implements Lis } @Override - public int remove(final T item) { + public final int remove(final T item) { int index = indexOf(item); if (index >= 0) { @@ -399,7 +445,7 @@ public class ArrayList<T> implements Lis @SuppressWarnings("unchecked") @Override - public Sequence<T> remove(final int index, final int count) { + public final Sequence<T> remove(final int index, final int count) { Utils.checkIndexBounds(index, count, 0, length); ArrayList<T> removed = new ArrayList<>((T[]) items, index, count); @@ -426,7 +472,7 @@ public class ArrayList<T> implements Lis } @Override - public void clear() { + public final void clear() { if (length > 0) { items = new Object[items.length]; length = 0; @@ -440,14 +486,14 @@ public class ArrayList<T> implements Lis @SuppressWarnings("unchecked") @Override - public T get(final int index) { + public final T get(final int index) { Utils.checkIndexBounds(index, 0, length - 1); return (T) items[index]; } @Override - public int indexOf(final T item) { + public final int indexOf(final T item) { int i; if (comparator == null) { @@ -458,22 +504,19 @@ public class ArrayList<T> implements Lis } return -1; } else { - // Perform a binary search to find the index - if ((i = binarySearch(this, item, comparator)) < 0) { - i = -1; - } - - return i; + // For a sorted list perform a binary search to find the index + i = binarySearch(this, item, comparator); + return (i < 0) ? -1 : i; } } @Override - public boolean isEmpty() { + public final boolean isEmpty() { return (length == 0); } @Override - public int getLength() { + public final int getLength() { return length; } @@ -481,12 +524,12 @@ public class ArrayList<T> implements Lis * Trim the internal storage for this list to exactly fit the current * number of items in it. */ - public void trimToSize() { - Object[] itemsLocal = new Object[length]; - System.arraycopy(this.items, 0, itemsLocal, 0, length); + public final void trimToSize() { + Object[] newItems = new Object[length]; + System.arraycopy(items, 0, newItems, 0, length); - this.items = itemsLocal; - length = itemsLocal.length; + items = newItems; + length = newItems.length; } /** @@ -501,13 +544,13 @@ public class ArrayList<T> implements Lis * * @param capacity The new capacity to allow for. */ - public void ensureCapacity(final int capacity) { + public final void ensureCapacity(final int capacity) { if (capacity > items.length) { - int capacityMax = Math.max(this.items.length * 3 / 2, capacity); - Object[] itemsLocal = new Object[capacityMax]; - System.arraycopy(this.items, 0, itemsLocal, 0, length); + int capacityMax = Math.max((int) (items.length * LOAD_FACTOR), capacity); + Object[] newItems = new Object[capacityMax]; + System.arraycopy(items, 0, newItems, 0, length); - this.items = itemsLocal; + items = newItems; } } @@ -515,14 +558,14 @@ public class ArrayList<T> implements Lis * @return The current capacity of the list, that is, how many items can be * stored before allocating more memory. */ - public int getCapacity() { + public final int getCapacity() { return items.length; } /** * @return The current contents of the list as an array of objects. */ - public Object[] toArray() { + public final Object[] toArray() { return Arrays.copyOf(items, length); } @@ -531,24 +574,24 @@ public class ArrayList<T> implements Lis * @param type The type of the array elements to be returned (which should * match the declared type of this ArrayList). */ - public T[] toArray(final Class<? extends T[]> type) { + public final T[] toArray(final Class<? extends T[]> type) { return Arrays.copyOf(items, length, type); } @Override - public Comparator<T> getComparator() { + public final Comparator<T> getComparator() { return comparator; } @Override - public void setComparator(final Comparator<T> comparator) { - Comparator<T> previousComparator = this.comparator; + public final void setComparator(final Comparator<T> newComparator) { + Comparator<T> previousComparator = comparator; - if (comparator != null) { - sort(this, comparator); + if (newComparator != null) { + sort(this, newComparator); } - this.comparator = comparator; + comparator = newComparator; if (listListeners != null) { listListeners.comparatorChanged(this, previousComparator); @@ -556,12 +599,12 @@ public class ArrayList<T> implements Lis } @Override - public ItemIterator<T> iterator() { + public final ItemIterator<T> iterator() { return new ArrayListItemIterator(); } @Override - public ListenerList<ListListener<T>> getListListeners() { + public final ListenerList<ListListener<T>> getListListeners() { if (listListeners == null) { listListeners = new ListListenerList<>(); } @@ -598,8 +641,12 @@ public class ArrayList<T> implements Lis @Override public int hashCode() { int hashCode = 1; - for (T item : this) { - hashCode = 31 * hashCode + (item == null ? 0 : item.hashCode()); + + for (Object item : items) { + hashCode *= HASH_MULTIPLIER; + if (item != null) { + hashCode += item.hashCode(); + } } return hashCode; @@ -615,32 +662,32 @@ public class ArrayList<T> implements Lis * Sort the current contents of the given list using the given comparator. * * @param <T> Type of the list elements. - * @param arrayList The list to sort. + * @param list The list to sort. * @param comparator The comparator to use to establish the sort order. */ - public static <T> void sort(final ArrayList<T> arrayList, final Comparator<T> comparator) { - sort(arrayList, 0, arrayList.getLength(), comparator); + public static final <T> void sort(final ArrayList<T> list, final Comparator<T> comparator) { + sort(list, 0, list.getLength(), comparator); } /** * Sort a portion of the given list. * * @param <T> Type of the list elements. - * @param arrayList The list to sort. + * @param list The list to sort. * @param from The beginning index in the list of the items to sort (inclusive). * @param to The ending index of the items to sort (exclusive), that is, the elements * from "from" to "to - 1" are sorted on return. * @param comparator The comparator to use to establish the sorted order. */ @SuppressWarnings("unchecked") - public static <T> void sort(final ArrayList<T> arrayList, final int from, final int to, + public static final <T> void sort(final ArrayList<T> list, final int from, final int to, final Comparator<T> comparator) { - Utils.checkNull(arrayList, "arrayList"); + Utils.checkNull(list, "list"); Utils.checkNull(comparator, "comparator"); - Arrays.sort((T[]) arrayList.items, from, to, comparator); + Arrays.sort((T[]) list.items, from, to, comparator); - arrayList.modificationCount++; + list.modificationCount++; } /** @@ -649,10 +696,10 @@ public class ArrayList<T> implements Lis * the {@link Comparable#compareTo} method to order the elements. * * @param <T> The comparable type of the elements in the list. - * @param arrayList The list to sort. + * @param list The list to sort. */ - public static <T extends Comparable<? super T>> void sort(final ArrayList<T> arrayList) { - sort(arrayList, (o1, o2) -> o1.compareTo(o2)); + public static final <T extends Comparable<? super T>> void sort(final ArrayList<T> list) { + sort(list, (o1, o2) -> o1.compareTo(o2)); } /** @@ -660,20 +707,20 @@ public class ArrayList<T> implements Lis * to establish the sort order of the elements. * * @param <T> Type of the list elements. - * @param arrayList The list to search. + * @param list The list to search. * @param item The item to search for in the list. * @param comparator Comparator to use for testing; if {@code null} then the "natural" ordering of the objects * is used (see the caveats of {@link Arrays#binarySearch(Object[], Object)}). * @return The index of the item in the list if found, or -1 if the item cannot be found in the list. */ @SuppressWarnings("unchecked") - public static <T> int binarySearch(final ArrayList<T> arrayList, final T item, final Comparator<T> comparator) { - Utils.checkNull(arrayList, "arrayList"); + public static final <T> int binarySearch(final ArrayList<T> list, final T item, final Comparator<T> comparator) { + Utils.checkNull(list, "list"); Utils.checkNull(item, "item"); int index = (comparator == null) - ? Arrays.binarySearch((T[]) arrayList.items, 0, arrayList.length, item) - : Arrays.binarySearch((T[]) arrayList.items, 0, arrayList.length, item, comparator); + ? Arrays.binarySearch((T[]) list.items, 0, list.length, item) + : Arrays.binarySearch((T[]) list.items, 0, list.length, item, comparator); return index; } @@ -682,12 +729,12 @@ public class ArrayList<T> implements Lis * Search for an item in the given list using the elements' "natural" ordering. * * @param <T> The comparable type of the elements in the list. - * @param arrayList The list to search. + * @param list The list to search. * @param item The item to search for. * @return The index of the item in the list if found, or -1 if the item is not found. */ - public static <T extends Comparable<? super T>> int binarySearch(final ArrayList<T> arrayList, final T item) { - return binarySearch(arrayList, item, null); + public static final <T extends Comparable<? super T>> int binarySearch(final ArrayList<T> list, final T item) { + return binarySearch(list, item, null); } } Modified: pivot/trunk/core/src/org/apache/pivot/collections/HashMap.java URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/collections/HashMap.java?rev=1913450&r1=1913449&r2=1913450&view=diff ============================================================================== --- pivot/trunk/core/src/org/apache/pivot/collections/HashMap.java (original) +++ pivot/trunk/core/src/org/apache/pivot/collections/HashMap.java Mon Oct 30 17:14:55 2023 @@ -27,29 +27,49 @@ import org.apache.pivot.util.ImmutableIt import org.apache.pivot.util.ListenerList; import org.apache.pivot.util.Utils; + /** * Implementation of the {@link Map} interface that is backed by a hash table. + * <p> Differs from the standard Java {@link java.util.HashMap} because it notifies + * its listeners for changes. This allows automatic updates of the UI whenever the + * underlying data in this structure changes. + * + * @param <K> Type of the key for elements in this map. + * @param <V> Type of value elements in the map. */ public class HashMap<K, V> implements Map<K, V>, Serializable { private static final long serialVersionUID = -7079717428744528670L; + /** + * Iterator over the keys of this map. + */ private class KeyIterator implements Iterator<K> { + /** Index of the bucket we are currently traversing. */ private int bucketIndex; + /** The iterator over the current bucket. */ private Iterator<Pair<K, V>> entryIterator; - private int countLocal; + /** Local modification count to detect changes to the map while iterating. */ + private int localIteratorCount; + /** Current entry while iterating. */ private Pair<K, V> entry = null; - public KeyIterator() { + /** + * Begin the iteration over the map keys. + */ + KeyIterator() { bucketIndex = 0; entryIterator = getBucketIterator(bucketIndex); - countLocal = HashMap.this.count; + localIteratorCount = HashMap.this.count; } + /** + * {@inheritDoc} + */ @Override public boolean hasNext() { - if (countLocal != HashMap.this.count) { + if (localIteratorCount != HashMap.this.count) { throw new ConcurrentModificationException(); } @@ -62,6 +82,9 @@ public class HashMap<K, V> implements Ma return (entryIterator != null); } + /** + * {@inheritDoc} + */ @Override public K next() { if (!hasNext()) { @@ -72,6 +95,9 @@ public class HashMap<K, V> implements Ma return entry.key; } + /** + * {@inheritDoc} + */ @Override public void remove() { if (entry == null || entryIterator == null) { @@ -79,7 +105,7 @@ public class HashMap<K, V> implements Ma } entryIterator.remove(); - countLocal--; + localIteratorCount--; HashMap.this.count--; if (mapListeners != null) { @@ -89,65 +115,142 @@ public class HashMap<K, V> implements Ma entry = null; } - private Iterator<Pair<K, V>> getBucketIterator(int bucketIndexArgument) { - LinkedList<Pair<K, V>> bucket = buckets.get(bucketIndexArgument); + /** + * Retrieve an iterator over the given bucket. + * + * @param index Index of the bucket to iterate over. + * @return The iterator over that bucket. + */ + private Iterator<Pair<K, V>> getBucketIterator(final int index) { + LinkedList<Pair<K, V>> bucket = buckets.get(index); return (bucket == null) ? new EmptyIterator<Pair<K, V>>() : bucket.iterator(); } } + /** + * The hash buckets for this map. + */ private ArrayList<LinkedList<Pair<K, V>>> buckets; + /** + * The desired load factor for this map. + */ private float loadFactor; + /** + * The current number of elements in this map. + */ private int count = 0; + /** + * The current list of keys in this map if we're sorting by them. + */ private ArrayList<K> keys = null; + /** + * The list of listeners for changes in this map. + */ private transient MapListener.Listeners<K, V> mapListeners = null; + /** + * The default initial capacity of this map. + */ public static final int DEFAULT_CAPACITY = 16; + /** + * The default load factor for this map. + */ public static final float DEFAULT_LOAD_FACTOR = 0.75f; + /** + * A hash multiiplier for computing the hash code for this map. + */ + private static final int HASH_MULTIPLIER = 31; + + /** + * Default constructor using default capacity and load factor. + */ public HashMap() { this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); } - public HashMap(int capacity) { + /** + * Construct a map sized for the given capacity, and using the default + * load factor. + * + * @param capacity The desired initial capacity of the map. + */ + public HashMap(final int capacity) { this(capacity, DEFAULT_LOAD_FACTOR); } - public HashMap(int capacity, float loadFactor) { - this.loadFactor = loadFactor; + /** + * Construct a map sized to the given capacity, using the given load factor. + * + * @param capacity The desired initial capacity of the map. + * @param load Desired load factor for scaling the capacity. + */ + public HashMap(final int capacity, final float load) { + loadFactor = load; rehash(capacity); } + /** + * Calculate an appropriate capacity, given the default load factor and the + * given number of initial entries to insert. + * + * @param size Size of an external map we are going to copy into this new one. + * @return An appropriate capacity for that size, given the default load factor. + */ + private static int capacityForSize(final int size) { + return Math.max((int) (size / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_CAPACITY); + } + + /** + * Construct a new map with the given initial entries. + * + * @param entries The initial map entries. + */ @SafeVarargs - public HashMap(Pair<K, V>... entries) { - this(Math.max((int) (entries.length / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_CAPACITY)); + public HashMap(final Pair<K, V>... entries) { + this(capacityForSize(entries.length)); - for (int i = 0; i < entries.length; i++) { - Pair<K, V> entry = entries[i]; + for (Pair<K, V> entry : entries) { put(entry.key, entry.value); } } - public HashMap(Map<K, V> map) { - this(Math.max((int) (map.getCount() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_CAPACITY)); + /** + * Construct a duplicate map from the given one. + * + * @param map The other map to copy into this one. + */ + public HashMap(final Map<K, V> map) { + this(capacityForSize(map.getCount())); for (K key : map) { put(key, map.get(key)); } } - public HashMap(java.util.Map<K, V> map) { - this(Math.max((int) (map.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_CAPACITY)); + /** + * Construct a duplicate map from the given standard map structure. + * + * @param map A standard {@link java.util.Map} to copy. + */ + public HashMap(final java.util.Map<K, V> map) { + this(capacityForSize(map.size())); for (K key : map.keySet()) { put(key, map.get(key)); } } - public HashMap(Comparator<K> comparator) { + /** + * Construct an ordered map using the given comparator. + * + * @param comparator Comparator used to sort the map keys. + */ + public HashMap(final Comparator<K> comparator) { this(); setComparator(comparator); @@ -159,7 +262,7 @@ public class HashMap<K, V> implements Ma * @throws IllegalArgumentException If {@code key} is {@literal null}. */ @Override - public V get(K key) { + public V get(final K key) { Utils.checkNull(key, "key"); V value = null; @@ -186,11 +289,22 @@ public class HashMap<K, V> implements Ma * @throws IllegalArgumentException If {@code key} is {@literal null}. */ @Override - public V put(K key, V value) { + public V put(final K key, final V value) { return put(key, value, true); } - private V put(K key, V value, boolean notifyListeners) { + /** + * Put an entry into this map, with or without notifying the listeners. + * <p> Not notifying will only happen during {@link #rehash} because nothing + * is changing during that process. + * + * @param key Key of the new entry. + * @param value Value for that key. + * @param notifyListeners Whether to notify the listeners of this change. + * @return The previous value (if any) for the key. + * @throws IllegalArgumentException if the key is {@literal null}. + */ + private V put(final K key, final V value, final boolean notifyListeners) { Utils.checkNull(key, "key"); V previousValue = null; @@ -248,7 +362,7 @@ public class HashMap<K, V> implements Ma * @throws IllegalArgumentException If {@code key} is {@literal null}. */ @Override - public V remove(K key) { + public V remove(final K key) { Utils.checkNull(key, "key"); V value = null; @@ -283,6 +397,9 @@ public class HashMap<K, V> implements Ma return value; } + /** + * {@inheritDoc} + */ @Override public void clear() { if (count > 0) { @@ -312,7 +429,7 @@ public class HashMap<K, V> implements Ma * @throws IllegalArgumentException If {@code key} is {@literal null}. */ @Override - public boolean containsKey(K key) { + public boolean containsKey(final K key) { Utils.checkNull(key, "key"); // Locate the entry @@ -333,25 +450,41 @@ public class HashMap<K, V> implements Ma return (i < bucket.getLength()); } + /** + * {@inheritDoc} + */ @Override public boolean isEmpty() { return (count == 0); } + /** + * {@inheritDoc} + */ @Override public int getCount() { return count; } + /** + * Retrieve the capacity of the map (that is, the number of buckets). + * + * @return The map's capacity. + */ public int getCapacity() { return buckets.getLength(); } - private void rehash(int capacity) { + /** + * Rebuild the map to the new capacity by rehashing the keys into the new set of buckets. + * + * @param newCapacity The enlarged new capacity of the map. + */ + private void rehash(final int newCapacity) { ArrayList<LinkedList<Pair<K, V>>> previousBuckets = this.buckets; - buckets = new ArrayList<>(capacity); + buckets = new ArrayList<>(newCapacity); - for (int i = 0; i < capacity; i++) { + for (int i = 0; i < newCapacity; i++) { buckets.add(null); } @@ -372,7 +505,13 @@ public class HashMap<K, V> implements Ma } } - private LinkedList<Pair<K, V>> getBucket(K key) { + /** + * Get the appropriate bucket for the given key. + * + * @param key Map key to be looked at. + * @return The currently correct map bucket for this key. + */ + private LinkedList<Pair<K, V>> getBucket(final K key) { int hashCode = key.hashCode(); int bucketIndex = Math.abs(hashCode % getCapacity()); @@ -385,13 +524,19 @@ public class HashMap<K, V> implements Ma return bucket; } + /** + * {@inheritDoc} + */ @Override public Comparator<K> getComparator() { return (keys == null) ? null : keys.getComparator(); } + /** + * {@inheritDoc} + */ @Override - public void setComparator(Comparator<K> comparator) { + public void setComparator(final Comparator<K> comparator) { Comparator<K> previousComparator = getComparator(); if (comparator == null) { @@ -415,11 +560,17 @@ public class HashMap<K, V> implements Ma } } + /** + * {@inheritDoc} + */ @Override public Iterator<K> iterator() { return (keys == null) ? new KeyIterator() : new ImmutableIterator<>(keys.iterator()); } + /** + * {@inheritDoc} + */ @Override public ListenerList<MapListener<K, V>> getMapListeners() { if (mapListeners == null) { @@ -429,9 +580,12 @@ public class HashMap<K, V> implements Ma return mapListeners; } + /** + * {@inheritDoc} + */ @Override @SuppressWarnings("unchecked") - public boolean equals(Object o) { + public boolean equals(final Object o) { boolean equals = false; if (this == o) { @@ -459,36 +613,42 @@ public class HashMap<K, V> implements Ma return equals; } + /** + * {@inheritDoc} + */ @Override public int hashCode() { int hashCode = 1; for (K key : this) { - hashCode = 31 * hashCode + key.hashCode(); + hashCode = HASH_MULTIPLIER * hashCode + key.hashCode(); } return hashCode; } + /** + * {@inheritDoc} + */ @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append(getClass().getName()); + sb.append(getClass().getSimpleName()); sb.append(" {"); int i = 0; for (K key : this) { - if (i > 0) { + if (i++ > 0) { sb.append(", "); } - sb.append(key + ":" + get(key)); - i++; + sb.append(key).append(": ").append(get(key)); } sb.append("}"); return sb.toString(); } + } Modified: pivot/trunk/core/src/org/apache/pivot/collections/LinkedList.java URL: http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/collections/LinkedList.java?rev=1913450&r1=1913449&r2=1913450&view=diff ============================================================================== --- pivot/trunk/core/src/org/apache/pivot/collections/LinkedList.java (original) +++ pivot/trunk/core/src/org/apache/pivot/collections/LinkedList.java Mon Oct 30 17:14:55 2023 @@ -37,6 +37,9 @@ import org.apache.pivot.util.Utils; public class LinkedList<T> implements List<T>, Serializable { private static final long serialVersionUID = 2100691224732602812L; + /** + * One node in the list, has the reference to the object as well as the links. + */ private static class Node<T> implements Serializable { private static final long serialVersionUID = -848937850230412572L; @@ -44,13 +47,16 @@ public class LinkedList<T> implements Li private Node<T> next; private T item; - public Node(final Node<T> previous, final Node<T> next, final T item) { - this.previous = previous; - this.next = next; - this.item = item; + public Node(final Node<T> previousNode, final Node<T> nextNode, final T listItem) { + this.previous = previousNode; + this.next = nextNode; + this.item = listItem; } } + /** + * Iterator over the items in the list. + */ private class LinkedListItemIterator implements ItemIterator<T> { private int index = 0; private Node<T> current = null; @@ -139,7 +145,7 @@ public class LinkedList<T> implements Li if (index == 0) { // Insert at head next = first; - // previous = null; // previous has already this value + // previous = null; // previous already has this value } else if (index < length) { if (forward) { // Insert after current @@ -152,7 +158,7 @@ public class LinkedList<T> implements Li } } else { // Insert at tail - // next = null; // next has already this value + // next = null; // next already has this value previous = last; } @@ -227,7 +233,6 @@ public class LinkedList<T> implements Li if (listListeners != null) { @SuppressWarnings("unchecked") - // or it will generate a warning during build with Java 7 LinkedList<T> removed = new LinkedList<>(item); listListeners.itemsRemoved(LinkedList.this, index, removed); @@ -244,13 +249,26 @@ public class LinkedList<T> implements Li private transient int modificationCount = 0; private transient ListListenerList<T> listListeners; + /** + * Default constructor of an empty unordered list. + */ public LinkedList() { } - public LinkedList(final Comparator<T> comparator) { - this.comparator = comparator; + /** + * Construct a new ordered list using the given comparator to do the ordering. + * + * @param newComparator Comparator to use for ordering this new list. + */ + public LinkedList(final Comparator<T> newComparator) { + this.comparator = newComparator; } + /** + * Construct a new list with the given initial items. + * + * @param items The initial set of items to add to the list. + */ @SafeVarargs public LinkedList(final T... items) { for (T item : items) { @@ -258,6 +276,11 @@ public class LinkedList<T> implements Li } } + /** + * Construct a new list with the given initial sequence of items. + * + * @param items The initial sequence of items for this list. + */ public LinkedList(final Sequence<T> items) { Utils.checkNull(items, "items"); @@ -326,6 +349,15 @@ public class LinkedList<T> implements Li } } + /** + * Insert this item into the list between the two nodes. + * + * @param item The new list item to insert. + * @param previous The node before this new one, can be {@literal null}. + * @param next Node after this new one, which can also be {@literal null}. + * @see #first + * @see #last + */ private void insert(final T item, final Node<T> previous, final Node<T> next) { Node<T> node = new Node<>(previous, next, item); @@ -366,6 +398,15 @@ public class LinkedList<T> implements Li return previousItem; } + /** + * For an ordered list (one having a comparator set) verify that the given item is in the + * proper place in the list, according to the comparator. + * + * @param item The new item to check. + * @param previous The proposed previous element in the list. + * @param next The proposed next element in the list. + * @throws IllegalArgumentException if the comparator is set and the item doesn't fit between these nodes. + */ private void verifyLocation(final T item, final Node<T> previous, final Node<T> next) { if (comparator != null) { // Ensure that the new item is greater or equal to its @@ -473,6 +514,17 @@ public class LinkedList<T> implements Li return node.item; } + /** + * Get the node at the given 0-based index location in the list. + * <p> Searches for the item from either the head or the tail of + * the list, depending on whether {@code index} is closer to 0 or + * the length of the list. + * + * @param index The index location. + * @return The node at the given index location in the list. + * @see #first + * @see #last + */ private Node<T> getNode(final int index) { Node<T> node; if (index == 0) {