Collections drop from Classpath:
2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> * java/util/BitSet.java (and): Fix off-by-one bug, don't skip part of the bitset. (andNot): Likewise. (xor): Likewise. 2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> * java/util/LinkedList.java (LinkedListItr.add): Don't skip the next entry. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/TreeMap.java (removeNode): Fix bug in node removal. 2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> * java/util/AbstractCollection.java (containsAll): Use size of the correct collection for loop bound. * java/util/AbstractList.java (iterator.next): Increment pos after calling get on backing list. (listIterator.next): Likewise. * java/util/LinkedList.java (addLastEntry): Don't increment size before checking for size == 0. (addFirstEntry): Rearrange to match addLastEntry. (add): Do not increment size before inserting the new entry. * java/util/AbstractCollection.java (addAll): Use size of the correct collection for loop bound. 2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> * java/util/AbstractSet.java (removeAll): Fix scoping thinko. * java/util/HashMap.java (putAllInternal): Set size here. * java/util/Hashtable.java (putAllInternal): New method. Copy contents of a map efficiently without calling put() or putAll(). (Hashtable (map)): Use putAllInternal. (clone): Likewise. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/Collections.java: * java/util/Vector.java: * java/util/WeakHashMap.java: Fix spelling errors. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/AbstractCollection.java (removeAllInternal), (retainAllInternal): Add hooks for use by ArrayList. * java/util/AbstractList.java: Minor code updates. Fix some scoping. * java/util/AbstractMap.java: ditto * java/util/ArrayList.java (readObject, writeObject): ditto (removeAllInternal, retainAllInternal): Optimize. * java/util/Arrays.java: ditto * java/util/Collections.java: ditto. Change order of parameters to equals(Object, Object) to match specs. * java/util/Dictionary.java: Improve javadoc. (Dictionary): Add explicit constructor. * java/util/HashMap.java: Improve javadoc. Rearrange methods to follow order in JDK. Cleanups related to recent code migration to AbstractMap. Fix some scoping. (entrySet): Cache the result. (modCount): Ensure that this is updated correctly. * java/util/HashSet.java: Improve javadoc. Fix some scoping. (init): Add hooks for LinkedHashSet. (map): Use "" instead of Boolean.TRUE in backing map. Use package-private API where possible for less overhead. (readObject, writeObject): Fix serialization. * java/util/Hashtable.java: Improve javadoc. Fix some scoping. (entrySet, keySet, values): Cache the result. (modCount): Ensure that this is updated correctly. (contains, remove): Fix NullPointer checking to match specs. (class Enumeration): Make more like HashIterator. * java/util/IdentityHashMap.java: Minor code updates. (modCount): Ensure that this is updated correctly. (readObject, writeObject): Fix serialization. * java/util/LinkedHashMap.java: Minor code updates. Cleanups related to recent code migration to AbstractMap. * java/util/LinkedHashSet.java: New file. * java/util/LinkedList.java: (readObject, writeObject): Fix serialization. * java/util/Makefile.am: List recently added files. * java/util/Stack.java: Minor code updates. * java/util/TreeMap.java: Improve javadoc. Overhaul the class to be more efficient. Fix some scoping. Rearrange the methods. (nil): Ensure that this can be thread-safe, and make it a static final. Initialize it to be more useful as a sentinal node. (Node): Specify color in constructor. (deleteFixup, insertFixup): Improve comments and algorithm. (fabricateTree): Redesign with less overhead. (lowestGreaterThan): Add parameter first to make SubMap easier. (removeNode): Patch hole where nil was being modified. Choose predecessor instead of successor so in-place swap works. (class VerifyResult, verifyTree, verifySub, verifyError): Remove this dead code after verifying the class works. (class SubMap): Rewrite several algorithms to avoid problems with comparing nil. * java/util/TreeSet.java: Improve javadoc. Fix some scoping. (clone): Fix ClassCastException when cloning subSet(). (readObject, writeObject): Fix serialization. * java/util/WeakHashMap.java: Improve javadoc. Fix some scoping. (NULL_KEY): Make it compare as null, for ease elsewhere. (Class WeakEntry): Rename from Entry, to avoid shadowing Map.Entry. Add missing toString. (modCount): Ensure that this is updated correctly. (clear, containsValue, keySet, putAll, values, WeakHashMap(Map)): Add missing methods and constructor. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/ArrayList.java (checkBoundExclusive), (checkBoundInclusive): Rename from range??clusive, to match AbstractList. * java/util/LinkedList.java (checkBoundsExclusive), (checkBoundsInclusive): ditto * java/util/Vector.java (checkBoundExclusive), (checkBoundInclusive): Move bounds checking into common methods. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/AbstractList.java: (modCount): Make sure it is updated in all needed places. * java/util/ArrayList.java: Improve javadoc. Implements RandomAccess. Add serialVersionUID. Reorder methods. (modCount): Make sure it is updated in all needed places. (rangeExclusive, rangeInclusive): Add common methods for bounds check. (isEmpty): Add missing method. * java/util/Collections.java: (class SynchronizedList): Make package visible. * java/util/ConcurrentModificationException.java: Improve javadoc. * java/util/EmptyStackException.java: Improve javadoc. * java/util/LinkedList.java: Improve javadoc. (modCount): Make sure it is updated in all needed places. (rangeExclusive, rangeInclusive): Add common methods for bounds check. * java/util/NoSuchElementException.java: Improve javadoc. * java/util/Stack.java: Improve javadoc. Fix synchronization issues. (modCount): Make sure it is updated in all needed places. * java/util/Vector.java: Improve javadoc. Fix synchronization issues. Implements RandomAccess. Reorder methods. (modCount): Make sure it is updated in all needed places. (setSize): Fix according to specifications: this does not dictate the backing array size. (removeAll, retainAll): Faster implementations. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/BitSet.java: Improve javadoc. (cardinality(), clear(), clear(int, int), flip(int)), (flip(int, int), get(int, int), intersects(BitSet), isEmpty()), (nextClearBit(int), nextSetBit(int), set(int, boolean)), (set(int, int), set(int, int, boolean)): Add new JDK 1.4 methods. (clone): Fix so subclasses clone correctly. 2001-12-15 Eric Blake <ebb9@email.byu.edu> * java/util/AbstractCollection.java: Improve javadoc. (AbstractCollection()): Make constructor protected. (equals(Object, Object), hashCode(Object)): Add utility methods. * java/util/AbstractList.java: Improve javadoc. (AbstractList()): Make constructor protected. (indexOf(Object)): Call listIterator(), not listIterator(int). (iterator()): Follow Sun's requirement to not use listIterator(0). (listIterator(int)): Make AbstractListItr anonymous. (subList(int, int)): Add support for RandomAccess. (SubList.add(int, Object), SubList.remove(Object)): Fix bug with modCount tracking. (SubList.addAll(Collection)): Add missing method. (SubList.listIterator(int)): Fix bugs in indexing, modCount tracking. (class RandomAccessSubList): Add new class. * java/util/AbstractMap.java: Improve javadoc. (keys, values, KEYS, VALUES, ENTRIES): Consolidate common map fields. (AbstractMap()): Make constructor protected. (equals(Object, Object), hashCode(Object)): Add utility methods. (equals(Object)): Change algorithm to entrySet().equals(m.entrySet()), as documented by Sun. (keySet(), values()): Cache the collections. * java/util/AbstractSequentialList.java: Improve javadoc. (AbstractSequentialList()): Make constructor protected. * java/util/AbstractSet.java: Improve javadoc. (AbstractSet()): Make constructor protected. (removeAll(Collection)): Add missing method. * java/util/Arrays.java: Improve javadoc, rearrange method orders. (defaultComparator): Remove, in favor of Collections.compare(Object, Object, Comparator). (binarySearch, equals, sort): Fix natural order comparison of floats and doubles. Also improve Object comparison - when comparator is null, use natural order. (fill, sort): Add missing checks for IllegalArgumentException. (sort, qsort): Fix sorting bugs, rework the code for more legibility. (mergeSort): Inline into sort(Object[], int, int, Comparator). (class ArrayList): Rename from ListImpl, and make compatible with JDK serialization. Add methods which more efficiently override those of AbstractList. * java/util/Collections: Improve javadoc. (isSequential(List)): Add and use a method for deciding between RandomAccess and sequential algorithms on lists. (class Empty*, class Synchronized*, class Unmodifiable*): Make compliant with JDK serializability. (class Singleton*, class CopiesList, class RevereseComparator), (class UnmodifiableMap.UnmodifiableEntrySet), (class *RandomAccessList): New classes for serial compatibility. (class Empty*, class Singleton*, class CopiesList): Add methods which more efficiently override those of Abstract*. (search): Inline into binarySearch(List, Object, Comparator). (binarySearch): Make sequential search only do log(n) comparisons, instead of n. (copy(List, List)): Do bounds checking before starting. (indexOfSubList, lastIndexOfSubList, list, replaceAll, rotate), (swap): Add new JDK 1.4 methods. (binarySearch, max, min, sort): Allow null comparator to represent natural ordering. (reverse(List)): Avoid unnecessary swap. (shuffle(List, Random)): Do shuffle in-place for RandomAccess lists. (SingletonList.get): Fix logic bug. (SingletonMap.entrySet): Make the entry immutable, and cache the returned set. (SynchronizedCollection, SynchronizedMap, UnmodifiableCollection), (UnmodifiableMap): Detect null pointer in construction. (SynchronizedMap, UnmodifiableMap): Cache collection views. * java/util/BasicMapEntry: Improve javadoc. From-SVN: r48035
This commit is contained in:
parent
def9790d51
commit
d9fd7154ec
27 changed files with 12307 additions and 6993 deletions
|
@ -1,4 +1,236 @@
|
||||||
|
2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
|
||||||
|
|
||||||
|
* java/util/BitSet.java (and): Fix off-by-one bug, don't skip part of
|
||||||
|
the bitset.
|
||||||
|
(andNot): Likewise.
|
||||||
|
(xor): Likewise.
|
||||||
|
|
||||||
|
2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
|
||||||
|
|
||||||
|
* java/util/LinkedList.java (LinkedListItr.add): Don't skip the next
|
||||||
|
entry.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/TreeMap.java (removeNode): Fix bug in node removal.
|
||||||
|
|
||||||
|
2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
|
||||||
|
|
||||||
|
* java/util/AbstractCollection.java (containsAll): Use size of the
|
||||||
|
correct collection for loop bound.
|
||||||
|
* java/util/AbstractList.java (iterator.next): Increment pos after
|
||||||
|
calling get on backing list.
|
||||||
|
(listIterator.next): Likewise.
|
||||||
|
* java/util/LinkedList.java (addLastEntry): Don't increment size before
|
||||||
|
checking for size == 0.
|
||||||
|
(addFirstEntry): Rearrange to match addLastEntry.
|
||||||
|
(add): Do not increment size before inserting the new entry.
|
||||||
|
|
||||||
|
* java/util/AbstractCollection.java (addAll): Use size of the
|
||||||
|
correct collection for loop bound.
|
||||||
|
|
||||||
|
2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz>
|
||||||
|
|
||||||
|
* java/util/AbstractSet.java (removeAll): Fix scoping thinko.
|
||||||
|
* java/util/HashMap.java (putAllInternal): Set size here.
|
||||||
|
* java/util/Hashtable.java (putAllInternal): New method. Copy contents
|
||||||
|
of a map efficiently without calling put() or putAll().
|
||||||
|
(Hashtable (map)): Use putAllInternal.
|
||||||
|
(clone): Likewise.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/Collections.java:
|
||||||
|
* java/util/Vector.java:
|
||||||
|
* java/util/WeakHashMap.java: Fix spelling errors.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/AbstractCollection.java (removeAllInternal),
|
||||||
|
(retainAllInternal): Add hooks for use by ArrayList.
|
||||||
|
* java/util/AbstractList.java: Minor code updates. Fix some
|
||||||
|
scoping.
|
||||||
|
* java/util/AbstractMap.java: ditto
|
||||||
|
* java/util/ArrayList.java (readObject, writeObject): ditto
|
||||||
|
(removeAllInternal, retainAllInternal): Optimize.
|
||||||
|
* java/util/Arrays.java: ditto
|
||||||
|
* java/util/Collections.java: ditto. Change order of parameters
|
||||||
|
to equals(Object, Object) to match specs.
|
||||||
|
* java/util/Dictionary.java: Improve javadoc.
|
||||||
|
(Dictionary): Add explicit constructor.
|
||||||
|
* java/util/HashMap.java: Improve javadoc. Rearrange methods to
|
||||||
|
follow order in JDK. Cleanups related to recent code migration to
|
||||||
|
AbstractMap. Fix some scoping.
|
||||||
|
(entrySet): Cache the result.
|
||||||
|
(modCount): Ensure that this is updated correctly.
|
||||||
|
* java/util/HashSet.java: Improve javadoc. Fix some scoping.
|
||||||
|
(init): Add hooks for LinkedHashSet.
|
||||||
|
(map): Use "" instead of Boolean.TRUE in backing map. Use
|
||||||
|
package-private API where possible for less overhead.
|
||||||
|
(readObject, writeObject): Fix serialization.
|
||||||
|
* java/util/Hashtable.java: Improve javadoc. Fix some scoping.
|
||||||
|
(entrySet, keySet, values): Cache the result.
|
||||||
|
(modCount): Ensure that this is updated correctly.
|
||||||
|
(contains, remove): Fix NullPointer checking to match specs.
|
||||||
|
(class Enumeration): Make more like HashIterator.
|
||||||
|
* java/util/IdentityHashMap.java: Minor code updates.
|
||||||
|
(modCount): Ensure that this is updated correctly.
|
||||||
|
(readObject, writeObject): Fix serialization.
|
||||||
|
* java/util/LinkedHashMap.java: Minor code updates. Cleanups
|
||||||
|
related to recent code migration to AbstractMap.
|
||||||
|
* java/util/LinkedHashSet.java: New file.
|
||||||
|
* java/util/LinkedList.java:
|
||||||
|
(readObject, writeObject): Fix serialization.
|
||||||
|
* java/util/Makefile.am: List recently added files.
|
||||||
|
* java/util/Stack.java: Minor code updates.
|
||||||
|
* java/util/TreeMap.java: Improve javadoc. Overhaul the class to
|
||||||
|
be more efficient. Fix some scoping. Rearrange the methods.
|
||||||
|
(nil): Ensure that this can be thread-safe, and make it a static
|
||||||
|
final. Initialize it to be more useful as a sentinal node.
|
||||||
|
(Node): Specify color in constructor.
|
||||||
|
(deleteFixup, insertFixup): Improve comments and algorithm.
|
||||||
|
(fabricateTree): Redesign with less overhead.
|
||||||
|
(lowestGreaterThan): Add parameter first to make SubMap easier.
|
||||||
|
(removeNode): Patch hole where nil was being modified. Choose
|
||||||
|
predecessor instead of successor so in-place swap works.
|
||||||
|
(class VerifyResult, verifyTree, verifySub, verifyError): Remove
|
||||||
|
this dead code after verifying the class works.
|
||||||
|
(class SubMap): Rewrite several algorithms to avoid problems with
|
||||||
|
comparing nil.
|
||||||
|
* java/util/TreeSet.java: Improve javadoc. Fix some scoping.
|
||||||
|
(clone): Fix ClassCastException when cloning subSet().
|
||||||
|
(readObject, writeObject): Fix serialization.
|
||||||
|
* java/util/WeakHashMap.java: Improve javadoc. Fix some scoping.
|
||||||
|
(NULL_KEY): Make it compare as null, for ease elsewhere.
|
||||||
|
(Class WeakEntry): Rename from Entry, to avoid shadowing
|
||||||
|
Map.Entry. Add missing toString.
|
||||||
|
(modCount): Ensure that this is updated correctly.
|
||||||
|
(clear, containsValue, keySet, putAll, values, WeakHashMap(Map)):
|
||||||
|
Add missing methods and constructor.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/ArrayList.java (checkBoundExclusive),
|
||||||
|
(checkBoundInclusive): Rename from range??clusive, to match
|
||||||
|
AbstractList.
|
||||||
|
* java/util/LinkedList.java (checkBoundsExclusive),
|
||||||
|
(checkBoundsInclusive): ditto
|
||||||
|
* java/util/Vector.java (checkBoundExclusive),
|
||||||
|
(checkBoundInclusive): Move bounds checking into common methods.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/AbstractList.java:
|
||||||
|
(modCount): Make sure it is updated in all needed places.
|
||||||
|
* java/util/ArrayList.java: Improve javadoc. Implements
|
||||||
|
RandomAccess. Add serialVersionUID. Reorder methods.
|
||||||
|
(modCount): Make sure it is updated in all needed places.
|
||||||
|
(rangeExclusive, rangeInclusive): Add common methods for bounds
|
||||||
|
check.
|
||||||
|
(isEmpty): Add missing method.
|
||||||
|
* java/util/Collections.java: (class SynchronizedList): Make
|
||||||
|
package visible.
|
||||||
|
* java/util/ConcurrentModificationException.java: Improve
|
||||||
|
javadoc.
|
||||||
|
* java/util/EmptyStackException.java: Improve javadoc.
|
||||||
|
* java/util/LinkedList.java: Improve javadoc.
|
||||||
|
(modCount): Make sure it is updated in all needed places.
|
||||||
|
(rangeExclusive, rangeInclusive): Add common methods for bounds
|
||||||
|
check.
|
||||||
|
* java/util/NoSuchElementException.java: Improve javadoc.
|
||||||
|
* java/util/Stack.java: Improve javadoc. Fix synchronization
|
||||||
|
issues.
|
||||||
|
(modCount): Make sure it is updated in all needed places.
|
||||||
|
* java/util/Vector.java: Improve javadoc. Fix synchronization
|
||||||
|
issues. Implements RandomAccess. Reorder methods.
|
||||||
|
(modCount): Make sure it is updated in all needed places.
|
||||||
|
(setSize): Fix according to specifications: this does not dictate
|
||||||
|
the backing array size.
|
||||||
|
(removeAll, retainAll): Faster implementations.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/BitSet.java: Improve javadoc.
|
||||||
|
(cardinality(), clear(), clear(int, int), flip(int)),
|
||||||
|
(flip(int, int), get(int, int), intersects(BitSet), isEmpty()),
|
||||||
|
(nextClearBit(int), nextSetBit(int), set(int, boolean)),
|
||||||
|
(set(int, int), set(int, int, boolean)): Add new JDK 1.4 methods.
|
||||||
|
(clone): Fix so subclasses clone correctly.
|
||||||
|
|
||||||
|
2001-12-15 Eric Blake <ebb9@email.byu.edu>
|
||||||
|
|
||||||
|
* java/util/AbstractCollection.java: Improve javadoc.
|
||||||
|
(AbstractCollection()): Make constructor protected.
|
||||||
|
(equals(Object, Object), hashCode(Object)): Add utility methods.
|
||||||
|
* java/util/AbstractList.java: Improve javadoc.
|
||||||
|
(AbstractList()): Make constructor protected.
|
||||||
|
(indexOf(Object)): Call listIterator(), not listIterator(int).
|
||||||
|
(iterator()): Follow Sun's requirement to not use listIterator(0).
|
||||||
|
(listIterator(int)): Make AbstractListItr anonymous.
|
||||||
|
(subList(int, int)): Add support for RandomAccess.
|
||||||
|
(SubList.add(int, Object), SubList.remove(Object)): Fix bug with
|
||||||
|
modCount tracking.
|
||||||
|
(SubList.addAll(Collection)): Add missing method.
|
||||||
|
(SubList.listIterator(int)): Fix bugs in indexing, modCount
|
||||||
|
tracking.
|
||||||
|
(class RandomAccessSubList): Add new class.
|
||||||
|
* java/util/AbstractMap.java: Improve javadoc.
|
||||||
|
(keys, values, KEYS, VALUES, ENTRIES): Consolidate common map
|
||||||
|
fields.
|
||||||
|
(AbstractMap()): Make constructor protected.
|
||||||
|
(equals(Object, Object), hashCode(Object)): Add utility methods.
|
||||||
|
(equals(Object)): Change algorithm to
|
||||||
|
entrySet().equals(m.entrySet()), as documented by Sun.
|
||||||
|
(keySet(), values()): Cache the collections.
|
||||||
|
* java/util/AbstractSequentialList.java: Improve javadoc.
|
||||||
|
(AbstractSequentialList()): Make constructor protected.
|
||||||
|
* java/util/AbstractSet.java: Improve javadoc.
|
||||||
|
(AbstractSet()): Make constructor protected.
|
||||||
|
(removeAll(Collection)): Add missing method.
|
||||||
|
* java/util/Arrays.java: Improve javadoc, rearrange method orders.
|
||||||
|
(defaultComparator): Remove, in favor of
|
||||||
|
Collections.compare(Object, Object, Comparator).
|
||||||
|
(binarySearch, equals, sort): Fix natural order comparison of
|
||||||
|
floats and doubles. Also improve Object comparison - when
|
||||||
|
comparator is null, use natural order.
|
||||||
|
(fill, sort): Add missing checks for IllegalArgumentException.
|
||||||
|
(sort, qsort): Fix sorting bugs, rework the code for more
|
||||||
|
legibility.
|
||||||
|
(mergeSort): Inline into sort(Object[], int, int, Comparator).
|
||||||
|
(class ArrayList): Rename from ListImpl, and make compatible with
|
||||||
|
JDK serialization. Add methods which more efficiently override
|
||||||
|
those of AbstractList.
|
||||||
|
* java/util/Collections: Improve javadoc.
|
||||||
|
(isSequential(List)): Add and use a method for deciding between
|
||||||
|
RandomAccess and sequential algorithms on lists.
|
||||||
|
(class Empty*, class Synchronized*, class Unmodifiable*): Make
|
||||||
|
compliant with JDK serializability.
|
||||||
|
(class Singleton*, class CopiesList, class RevereseComparator),
|
||||||
|
(class UnmodifiableMap.UnmodifiableEntrySet),
|
||||||
|
(class *RandomAccessList): New classes for serial compatibility.
|
||||||
|
(class Empty*, class Singleton*, class CopiesList): Add methods
|
||||||
|
which more efficiently override those of Abstract*.
|
||||||
|
(search): Inline into binarySearch(List, Object, Comparator).
|
||||||
|
(binarySearch): Make sequential search only do log(n) comparisons,
|
||||||
|
instead of n.
|
||||||
|
(copy(List, List)): Do bounds checking before starting.
|
||||||
|
(indexOfSubList, lastIndexOfSubList, list, replaceAll, rotate),
|
||||||
|
(swap): Add new JDK 1.4 methods.
|
||||||
|
(binarySearch, max, min, sort): Allow null comparator to represent
|
||||||
|
natural ordering.
|
||||||
|
(reverse(List)): Avoid unnecessary swap.
|
||||||
|
(shuffle(List, Random)): Do shuffle in-place for RandomAccess
|
||||||
|
lists.
|
||||||
|
(SingletonList.get): Fix logic bug.
|
||||||
|
(SingletonMap.entrySet): Make the entry immutable, and cache the
|
||||||
|
returned set.
|
||||||
|
(SynchronizedCollection, SynchronizedMap, UnmodifiableCollection),
|
||||||
|
(UnmodifiableMap): Detect null pointer in construction.
|
||||||
|
(SynchronizedMap, UnmodifiableMap): Cache collection views.
|
||||||
|
* java/util/BasicMapEntry: Improve javadoc.
|
||||||
|
|
||||||
2001-12-14 Hans Boehm <Hans_Boehm@hp.com>
|
2001-12-14 Hans Boehm <Hans_Boehm@hp.com>
|
||||||
|
|
||||||
* libjava/prims.cc: Some old cleanups. The collector now
|
* libjava/prims.cc: Some old cleanups. The collector now
|
||||||
handles test for out of memory.
|
handles test for out of memory.
|
||||||
|
|
||||||
|
|
|
@ -1200,6 +1200,7 @@ java/util/IdentityHashMap.java \
|
||||||
java/util/Iterator.java \
|
java/util/Iterator.java \
|
||||||
java/util/LinkedList.java \
|
java/util/LinkedList.java \
|
||||||
java/util/LinkedHashMap.java \
|
java/util/LinkedHashMap.java \
|
||||||
|
java/util/LinkedHashSet.java \
|
||||||
java/util/List.java \
|
java/util/List.java \
|
||||||
java/util/ListIterator.java \
|
java/util/ListIterator.java \
|
||||||
java/util/ListResourceBundle.java \
|
java/util/ListResourceBundle.java \
|
||||||
|
|
|
@ -123,19 +123,13 @@ libgcj_basedir = @libgcj_basedir@
|
||||||
mkinstalldirs = @mkinstalldirs@
|
mkinstalldirs = @mkinstalldirs@
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign
|
AUTOMAKE_OPTIONS = foreign
|
||||||
@TESTSUBDIR_TRUE@SUBDIRS = \
|
@TESTSUBDIR_TRUE@SUBDIRS = @TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
|
||||||
@TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
|
@TESTSUBDIR_FALSE@SUBDIRS = @TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
|
||||||
@TESTSUBDIR_FALSE@SUBDIRS = \
|
@USE_LIBDIR_TRUE@toolexeclibdir = @USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
|
||||||
@TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
|
@USE_LIBDIR_FALSE@toolexeclibdir = @USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
|
||||||
@USE_LIBDIR_TRUE@toolexeclibdir = \
|
@USE_LIBDIR_FALSE@toolexecdir = @USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
|
||||||
@USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
|
@XLIB_AWT_TRUE@cond_x_ltlibrary = @XLIB_AWT_TRUE@libgcjx.la
|
||||||
@USE_LIBDIR_FALSE@toolexeclibdir = \
|
@XLIB_AWT_FALSE@cond_x_ltlibrary =
|
||||||
@USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
|
|
||||||
@USE_LIBDIR_FALSE@toolexecdir = \
|
|
||||||
@USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
|
|
||||||
@XLIB_AWT_TRUE@cond_x_ltlibrary = \
|
|
||||||
@XLIB_AWT_TRUE@libgcjx.la
|
|
||||||
@XLIB_AWT_FALSE@cond_x_ltlibrary = \
|
|
||||||
|
|
||||||
toolexeclib_LTLIBRARIES = libgcj.la $(cond_x_ltlibrary)
|
toolexeclib_LTLIBRARIES = libgcj.la $(cond_x_ltlibrary)
|
||||||
toolexeclib_DATA = libgcj.spec
|
toolexeclib_DATA = libgcj.spec
|
||||||
|
@ -143,20 +137,14 @@ data_DATA = libgcj.jar
|
||||||
|
|
||||||
secdir = $(libdir)/security
|
secdir = $(libdir)/security
|
||||||
|
|
||||||
@NATIVE_TRUE@bin_PROGRAMS = \
|
@NATIVE_TRUE@bin_PROGRAMS = @NATIVE_TRUE@jv-convert gij rmic rmiregistry
|
||||||
@NATIVE_TRUE@jv-convert gij rmic rmiregistry
|
|
||||||
|
|
||||||
bin_SCRIPTS = addr2name.awk
|
bin_SCRIPTS = addr2name.awk
|
||||||
@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = \
|
@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
|
||||||
@CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
|
@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
|
||||||
@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = \
|
@CANADIAN_FALSE@ZIP = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
|
||||||
@CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
|
@CANADIAN_TRUE@GCJH = @CANADIAN_TRUE@gcjh
|
||||||
@CANADIAN_FALSE@ZIP = \
|
@CANADIAN_FALSE@GCJH = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
|
||||||
@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
|
|
||||||
@CANADIAN_TRUE@GCJH = \
|
|
||||||
@CANADIAN_TRUE@gcjh
|
|
||||||
@CANADIAN_FALSE@GCJH = \
|
|
||||||
@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
|
|
||||||
|
|
||||||
GCJ_WITH_FLAGS = $(GCJ) --encoding=UTF-8
|
GCJ_WITH_FLAGS = $(GCJ) --encoding=UTF-8
|
||||||
|
|
||||||
|
@ -176,10 +164,8 @@ AM_CXXFLAGS = -fno-rtti -fnon-call-exceptions \
|
||||||
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE \
|
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE \
|
||||||
-DPREFIX="\"$(prefix)\""
|
-DPREFIX="\"$(prefix)\""
|
||||||
|
|
||||||
@USING_GCC_TRUE@AM_CFLAGS = \
|
@USING_GCC_TRUE@AM_CFLAGS = @USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
|
||||||
@USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
|
@USING_GCC_FALSE@AM_CFLAGS = @USING_GCC_FALSE@@LIBGCJ_CFLAGS@
|
||||||
@USING_GCC_FALSE@AM_CFLAGS = \
|
|
||||||
@USING_GCC_FALSE@@LIBGCJ_CFLAGS@
|
|
||||||
|
|
||||||
JCFLAGS = -g
|
JCFLAGS = -g
|
||||||
JC1FLAGS = @LIBGCJ_JAVAFLAGS@ $(GCJFLAGS)
|
JC1FLAGS = @LIBGCJ_JAVAFLAGS@ $(GCJFLAGS)
|
||||||
|
@ -252,8 +238,7 @@ extra_headers = java/lang/Object.h java/lang/Class.h
|
||||||
|
|
||||||
NM = nm
|
NM = nm
|
||||||
|
|
||||||
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = \
|
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = @NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
|
||||||
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
|
|
||||||
|
|
||||||
CONVERT_DIR = gnu/gcj/convert
|
CONVERT_DIR = gnu/gcj/convert
|
||||||
|
|
||||||
|
@ -950,6 +935,7 @@ java/util/IdentityHashMap.java \
|
||||||
java/util/Iterator.java \
|
java/util/Iterator.java \
|
||||||
java/util/LinkedList.java \
|
java/util/LinkedList.java \
|
||||||
java/util/LinkedHashMap.java \
|
java/util/LinkedHashMap.java \
|
||||||
|
java/util/LinkedHashSet.java \
|
||||||
java/util/List.java \
|
java/util/List.java \
|
||||||
java/util/ListIterator.java \
|
java/util/ListIterator.java \
|
||||||
java/util/ListResourceBundle.java \
|
java/util/ListResourceBundle.java \
|
||||||
|
@ -1585,7 +1571,7 @@ libgcj-test.spec.in libgcj.spec.in
|
||||||
|
|
||||||
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
|
||||||
TAR = tar
|
TAR = gtar
|
||||||
GZIP_ENV = --best
|
GZIP_ENV = --best
|
||||||
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
|
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
|
||||||
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
|
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
|
||||||
|
@ -2224,10 +2210,11 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
|
||||||
.deps/java/util/GregorianCalendar.P .deps/java/util/HashMap.P \
|
.deps/java/util/GregorianCalendar.P .deps/java/util/HashMap.P \
|
||||||
.deps/java/util/HashSet.P .deps/java/util/Hashtable.P \
|
.deps/java/util/HashSet.P .deps/java/util/Hashtable.P \
|
||||||
.deps/java/util/IdentityHashMap.P .deps/java/util/Iterator.P \
|
.deps/java/util/IdentityHashMap.P .deps/java/util/Iterator.P \
|
||||||
.deps/java/util/LinkedHashMap.P .deps/java/util/LinkedList.P \
|
.deps/java/util/LinkedHashMap.P .deps/java/util/LinkedHashSet.P \
|
||||||
.deps/java/util/List.P .deps/java/util/ListIterator.P \
|
.deps/java/util/LinkedList.P .deps/java/util/List.P \
|
||||||
.deps/java/util/ListResourceBundle.P .deps/java/util/Locale.P \
|
.deps/java/util/ListIterator.P .deps/java/util/ListResourceBundle.P \
|
||||||
.deps/java/util/Map.P .deps/java/util/MissingResourceException.P \
|
.deps/java/util/Locale.P .deps/java/util/Map.P \
|
||||||
|
.deps/java/util/MissingResourceException.P \
|
||||||
.deps/java/util/NoSuchElementException.P .deps/java/util/Observable.P \
|
.deps/java/util/NoSuchElementException.P .deps/java/util/Observable.P \
|
||||||
.deps/java/util/Observer.P .deps/java/util/Properties.P \
|
.deps/java/util/Observer.P .deps/java/util/Properties.P \
|
||||||
.deps/java/util/PropertyPermission.P \
|
.deps/java/util/PropertyPermission.P \
|
||||||
|
@ -2735,7 +2722,7 @@ distdir: $(DISTFILES)
|
||||||
@for file in $(DISTFILES); do \
|
@for file in $(DISTFILES); do \
|
||||||
d=$(srcdir); \
|
d=$(srcdir); \
|
||||||
if test -d $$d/$$file; then \
|
if test -d $$d/$$file; then \
|
||||||
cp -pr $$/$$file $(distdir)/$$file; \
|
cp -pr $$d/$$file $(distdir)/$$file; \
|
||||||
else \
|
else \
|
||||||
test -f $(distdir)/$$file \
|
test -f $(distdir)/$$file \
|
||||||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractCollection.java -- Abstract implementation of most of Collection
|
/* AbstractCollection.java -- Abstract implementation of most of Collection
|
||||||
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -42,77 +42,119 @@ import java.lang.reflect.Array;
|
||||||
* backing data structure allows for a more efficient implementation. The
|
* backing data structure allows for a more efficient implementation. The
|
||||||
* precise implementation used by AbstractCollection is documented, so that
|
* precise implementation used by AbstractCollection is documented, so that
|
||||||
* subclasses can tell which methods could be implemented more efficiently.
|
* subclasses can tell which methods could be implemented more efficiently.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The programmer should provide a no-argument constructor, and one that
|
||||||
|
* accepts another Collection, as recommended by the Collection interface.
|
||||||
|
* Unfortunately, there is no way to enforce this in Java.
|
||||||
|
*
|
||||||
|
* @author Original author unknown
|
||||||
|
* @author Bryce McKinlay
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see AbstractSet
|
||||||
|
* @see AbstractList
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCollection implements Collection
|
public abstract class AbstractCollection implements Collection
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The main constructor, for use by subclasses.
|
||||||
|
*/
|
||||||
|
protected AbstractCollection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an Iterator over this collection. The iterator must provide the
|
* Return an Iterator over this collection. The iterator must provide the
|
||||||
* hasNext and next methods and should in addition provide remove if the
|
* hasNext and next methods and should in addition provide remove if the
|
||||||
* collection is modifiable.
|
* collection is modifiable.
|
||||||
|
*
|
||||||
|
* @return an iterator
|
||||||
*/
|
*/
|
||||||
public abstract Iterator iterator();
|
public abstract Iterator iterator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the number of elements in this collection.
|
* Return the number of elements in this collection. If there are more than
|
||||||
|
* Integer.MAX_VALUE elements, return Integer.MAX_VALUE.
|
||||||
|
*
|
||||||
|
* @return the size
|
||||||
*/
|
*/
|
||||||
public abstract int size();
|
public abstract int size();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an object to the collection. This implementation always throws an
|
* Add an object to the collection (optional operation). This implementation
|
||||||
* UnsupportedOperationException - it should be overridden if the collection
|
* always throws an UnsupportedOperationException - it should be
|
||||||
* is to be modifiable.
|
* overridden if the collection is to be modifiable. If the collection
|
||||||
|
* does not accept duplicates, simply return false. Collections may specify
|
||||||
|
* limitations on what may be added.
|
||||||
*
|
*
|
||||||
* @param o the object to add
|
* @param o the object to add
|
||||||
* @return true if the add operation caused the Collection to change
|
* @return true if the add operation caused the Collection to change
|
||||||
* @exception UnsupportedOperationException if the add operation is not
|
* @throws UnsupportedOperationException if the add operation is not
|
||||||
* supported on this collection
|
* supported on this collection
|
||||||
|
* @throws NullPointerException if the collection does not support null
|
||||||
|
* @throws ClassCastException if the object is of the wrong type
|
||||||
|
* @throws IllegalArgumentException if some aspect of the object prevents
|
||||||
|
* it from being added
|
||||||
*/
|
*/
|
||||||
public boolean add(Object o)
|
public boolean add(Object o)
|
||||||
{
|
{
|
||||||
throw new java.lang.UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all the elements of a given collection to this collection. This
|
* Add all the elements of a given collection to this collection (optional
|
||||||
* implementation obtains an Iterator over the given collection and iterates
|
* operation). This implementation obtains an Iterator over the given
|
||||||
* over it, adding each element with the add(Object) method (thus this method
|
* collection and iterates over it, adding each element with the
|
||||||
* will fail with an UnsupportedOperationException if the add method does).
|
* add(Object) method (thus this method will fail with an
|
||||||
|
* UnsupportedOperationException if the add method does). The behavior is
|
||||||
|
* unspecified if the specified collection is modified during the iteration,
|
||||||
|
* including the special case of trying addAll(this) on a non-empty
|
||||||
|
* collection.
|
||||||
*
|
*
|
||||||
* @param c the collection to add the elements of to this collection
|
* @param c the collection to add the elements of to this collection
|
||||||
* @return true if the add operation caused the Collection to change
|
* @return true if the add operation caused the Collection to change
|
||||||
* @exception UnsupportedOperationException if the add operation is not
|
* @throws UnsupportedOperationException if the add operation is not
|
||||||
* supported on this collection
|
* supported on this collection
|
||||||
|
* @throws NullPointerException if this collection does not support null,
|
||||||
|
* or if the specified collection is null
|
||||||
|
* @throws ClassCastException if an object in c is of the wrong type
|
||||||
|
* @throws IllegalArgumentException if some aspect of an object in c prevents
|
||||||
|
* it from being added
|
||||||
|
* @see #add(Object)
|
||||||
*/
|
*/
|
||||||
public boolean addAll(Collection c)
|
public boolean addAll(Collection c)
|
||||||
{
|
{
|
||||||
Iterator itr = c.iterator();
|
Iterator itr = c.iterator();
|
||||||
int size = c.size();
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (int pos = 0; pos < size; pos++)
|
int pos = c.size();
|
||||||
{
|
while (--pos >= 0)
|
||||||
modified |= add(itr.next());
|
modified |= add(itr.next());
|
||||||
}
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all elements from the collection. This implementation obtains an
|
* Remove all elements from the collection (optional operation). This
|
||||||
* iterator over the collection and calls next and remove on it repeatedly
|
* implementation obtains an iterator over the collection and calls next
|
||||||
* (thus this method will fail with an UnsupportedOperationException if the
|
* and remove on it repeatedly (thus this method will fail with an
|
||||||
* Iterator's remove method does) until there are no more elements to remove.
|
* UnsupportedOperationException if the Iterator's remove method does)
|
||||||
|
* until there are no more elements to remove.
|
||||||
* Many implementations will have a faster way of doing this.
|
* Many implementations will have a faster way of doing this.
|
||||||
*
|
*
|
||||||
* @exception UnsupportedOperationException if the Iterator returned by
|
* @throws UnsupportedOperationException if the Iterator returned by
|
||||||
* iterator does not provide an implementation of remove
|
* iterator does not provide an implementation of remove
|
||||||
|
* @see Iterator#remove()
|
||||||
*/
|
*/
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
int pos = size();
|
||||||
for (int pos = 0; pos < size; pos++)
|
while (--pos >= 0)
|
||||||
{
|
{
|
||||||
itr.next();
|
itr.next();
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,12 +172,10 @@ public abstract class AbstractCollection implements Collection
|
||||||
public boolean contains(Object o)
|
public boolean contains(Object o)
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
int pos = size();
|
||||||
for (int pos = 0; pos < size; pos++)
|
while (--pos >= 0)
|
||||||
{
|
if (equals(o, itr.next()))
|
||||||
if (o == null ? itr.next() == null : o.equals(itr.next()))
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,17 +187,17 @@ public abstract class AbstractCollection implements Collection
|
||||||
*
|
*
|
||||||
* @param c the collection to test against
|
* @param c the collection to test against
|
||||||
* @return true if this collection contains all the elements in the given
|
* @return true if this collection contains all the elements in the given
|
||||||
* collection
|
* collection
|
||||||
|
* @throws NullPointerException if the given collection is null
|
||||||
|
* @see #contains(Object)
|
||||||
*/
|
*/
|
||||||
public boolean containsAll(Collection c)
|
public boolean containsAll(Collection c)
|
||||||
{
|
{
|
||||||
Iterator itr = c.iterator();
|
Iterator itr = c.iterator();
|
||||||
int size = c.size();
|
int pos = c.size();
|
||||||
for (int pos = 0; pos < size; pos++)
|
while (--pos >= 0)
|
||||||
{
|
if (!contains(itr.next()))
|
||||||
if (!contains(itr.next()))
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,6 +206,7 @@ public abstract class AbstractCollection implements Collection
|
||||||
* size() == 0.
|
* size() == 0.
|
||||||
*
|
*
|
||||||
* @return true if this collection is empty.
|
* @return true if this collection is empty.
|
||||||
|
* @see #size()
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty()
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
|
@ -173,92 +214,131 @@ public abstract class AbstractCollection implements Collection
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a single instance of an object from this collection. That is,
|
* Remove a single instance of an object from this collection (optional
|
||||||
* remove one element e such that (o == null ? e == null : o.equals(e)), if
|
* operation). That is, remove one element e such that
|
||||||
* such an element exists. This implementation obtains an iterator over the
|
* <code>(o == null ? e == null : o.equals(e))</code>, if such an element
|
||||||
* collection and iterates over it, testing each element for equality with
|
* exists. This implementation obtains an iterator over the collection
|
||||||
* the given object. If it is equal, it is removed by the iterator's remove
|
* and iterates over it, testing each element for equality with the given
|
||||||
* method (thus this method will fail with an UnsupportedOperationException
|
* object. If it is equal, it is removed by the iterator's remove method
|
||||||
* if the Iterator's remove method does). After the first element has been
|
* (thus this method will fail with an UnsupportedOperationException if
|
||||||
|
* the Iterator's remove method does). After the first element has been
|
||||||
* removed, true is returned; if the end of the collection is reached, false
|
* removed, true is returned; if the end of the collection is reached, false
|
||||||
* is returned.
|
* is returned.
|
||||||
*
|
*
|
||||||
* @param o the object to remove from this collection
|
* @param o the object to remove from this collection
|
||||||
* @return true if the remove operation caused the Collection to change, or
|
* @return true if the remove operation caused the Collection to change, or
|
||||||
* equivalently if the collection did contain o.
|
* equivalently if the collection did contain o.
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator
|
* @throws UnsupportedOperationException if this collection's Iterator
|
||||||
* does not support the remove method
|
* does not support the remove method
|
||||||
|
* @see Iterator#remove()
|
||||||
*/
|
*/
|
||||||
public boolean remove(Object o)
|
public boolean remove(Object o)
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
int pos = size();
|
||||||
for (int pos = 0; pos < size; pos++)
|
while (--pos >= 0)
|
||||||
{
|
if (equals(o, itr.next()))
|
||||||
if (o == null ? itr.next() == null : o.equals(itr.next()))
|
{
|
||||||
{
|
itr.remove();
|
||||||
itr.remove();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove from this collection all its elements that are contained in a given
|
* Remove from this collection all its elements that are contained in a given
|
||||||
* collection. This implementation iterates over this collection, and for
|
* collection (optional operation). This implementation iterates over this
|
||||||
* each element tests if it is contained in the given collection. If so, it
|
* collection, and for each element tests if it is contained in the given
|
||||||
* is removed by the Iterator's remove method (thus this method will fail
|
* collection. If so, it is removed by the Iterator's remove method (thus
|
||||||
* with an UnsupportedOperationException if the Iterator's remove method
|
* this method will fail with an UnsupportedOperationException if the
|
||||||
* does).
|
* Iterator's remove method does).
|
||||||
*
|
*
|
||||||
* @param c the collection to remove the elements of
|
* @param c the collection to remove the elements of
|
||||||
* @return true if the remove operation caused the Collection to change
|
* @return true if the remove operation caused the Collection to change
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator
|
* @throws UnsupportedOperationException if this collection's Iterator
|
||||||
* does not support the remove method
|
* does not support the remove method
|
||||||
|
* @see Iterator#remove()
|
||||||
*/
|
*/
|
||||||
public boolean removeAll(Collection c)
|
public boolean removeAll(Collection c)
|
||||||
|
{
|
||||||
|
return removeAllInternal(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from this collection all its elements that are contained in a given
|
||||||
|
* collection (optional operation). This implementation iterates over this
|
||||||
|
* collection, and for each element tests if it is contained in the given
|
||||||
|
* collection. If so, it is removed by the Iterator's remove method (thus
|
||||||
|
* this method will fail with an UnsupportedOperationException if the
|
||||||
|
* Iterator's remove method does). This method is necessary for ArrayList,
|
||||||
|
* which cannot publicly override removeAll but can optimize this call.
|
||||||
|
*
|
||||||
|
* @param c the collection to remove the elements of
|
||||||
|
* @return true if the remove operation caused the Collection to change
|
||||||
|
* @throws UnsupportedOperationException if this collection's Iterator
|
||||||
|
* does not support the remove method
|
||||||
|
* @see Iterator#remove()
|
||||||
|
*/
|
||||||
|
boolean removeAllInternal(Collection c)
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (int pos = 0; pos < size; pos++)
|
int pos = size();
|
||||||
{
|
while (--pos >= 0)
|
||||||
if (c.contains(itr.next()))
|
if (c.contains(itr.next()))
|
||||||
{
|
{
|
||||||
itr.remove();
|
itr.remove();
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove from this collection all its elements that are not contained in a
|
* Remove from this collection all its elements that are not contained in a
|
||||||
* given collection. This implementation iterates over this collection, and
|
* given collection (optional operation). This implementation iterates over
|
||||||
* for each element tests if it is contained in the given collection. If not,
|
* this collection, and for each element tests if it is contained in the
|
||||||
* it is removed by the Iterator's remove method (thus this method will fail
|
* given collection. If not, it is removed by the Iterator's remove method
|
||||||
* with an UnsupportedOperationException if the Iterator's remove method
|
* (thus this method will fail with an UnsupportedOperationException if
|
||||||
* does).
|
* the Iterator's remove method does).
|
||||||
*
|
*
|
||||||
* @param c the collection to retain the elements of
|
* @param c the collection to retain the elements of
|
||||||
* @return true if the remove operation caused the Collection to change
|
* @return true if the remove operation caused the Collection to change
|
||||||
* @exception UnsupportedOperationException if this collection's Iterator
|
* @throws UnsupportedOperationException if this collection's Iterator
|
||||||
* does not support the remove method
|
* does not support the remove method
|
||||||
|
* @see Iterator#remove()
|
||||||
*/
|
*/
|
||||||
public boolean retainAll(Collection c)
|
public boolean retainAll(Collection c)
|
||||||
|
{
|
||||||
|
return retainAllInternal(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from this collection all its elements that are not contained in a
|
||||||
|
* given collection (optional operation). This implementation iterates over
|
||||||
|
* this collection, and for each element tests if it is contained in the
|
||||||
|
* given collection. If not, it is removed by the Iterator's remove method
|
||||||
|
* (thus this method will fail with an UnsupportedOperationException if
|
||||||
|
* the Iterator's remove method does). This method is necessary for
|
||||||
|
* ArrayList, which cannot publicly override retainAll but can optimize
|
||||||
|
* this call.
|
||||||
|
*
|
||||||
|
* @param c the collection to retain the elements of
|
||||||
|
* @return true if the remove operation caused the Collection to change
|
||||||
|
* @throws UnsupportedOperationException if this collection's Iterator
|
||||||
|
* does not support the remove method
|
||||||
|
* @see Iterator#remove()
|
||||||
|
*/
|
||||||
|
boolean retainAllInternal(Collection c)
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (int pos = 0; pos < size; pos++)
|
int pos = size();
|
||||||
{
|
while (--pos >= 0)
|
||||||
if (!c.contains(itr.next()))
|
if (!c.contains(itr.next()))
|
||||||
{
|
{
|
||||||
itr.remove();
|
itr.remove();
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,18 +346,18 @@ public abstract class AbstractCollection implements Collection
|
||||||
* Return an array containing the elements of this collection. This
|
* Return an array containing the elements of this collection. This
|
||||||
* implementation creates an Object array of size size() and then iterates
|
* implementation creates an Object array of size size() and then iterates
|
||||||
* over the collection, setting each element of the array from the value
|
* over the collection, setting each element of the array from the value
|
||||||
* returned by the iterator.
|
* returned by the iterator. The returned array is safe, and is not backed
|
||||||
|
* by the collection.
|
||||||
*
|
*
|
||||||
* @return an array containing the elements of this collection
|
* @return an array containing the elements of this collection
|
||||||
*/
|
*/
|
||||||
public Object[] toArray()
|
public Object[] toArray()
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
Object[]a = new Object[size()];
|
int size = size();
|
||||||
for (int pos = 0; pos < a.length; pos++)
|
Object[] a = new Object[size];
|
||||||
{
|
for (int pos = 0; pos < size; pos++)
|
||||||
a[pos] = itr.next();
|
a[pos] = itr.next();
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,29 +373,29 @@ public abstract class AbstractCollection implements Collection
|
||||||
* obtained over the collection and the elements are placed in the array as
|
* obtained over the collection and the elements are placed in the array as
|
||||||
* they are returned by the iterator. Finally the first spare element, if
|
* they are returned by the iterator. Finally the first spare element, if
|
||||||
* any, of the array is set to null, and the created array is returned.
|
* any, of the array is set to null, and the created array is returned.
|
||||||
|
* The returned array is safe; it is not backed by the collection. Note that
|
||||||
|
* null may not mark the last element, if the collection allows null
|
||||||
|
* elements.
|
||||||
*
|
*
|
||||||
* @param a the array to copy into, or of the correct run-time type
|
* @param a the array to copy into, or of the correct run-time type
|
||||||
* @return the array that was produced
|
* @return the array that was produced
|
||||||
* @exception ClassCastException if the type of the array precludes holding
|
* @throws NullPointerException if the given array is null
|
||||||
* one of the elements of the Collection
|
* @throws ArrayStoreException if the type of the array precludes holding
|
||||||
|
* one of the elements of the Collection
|
||||||
*/
|
*/
|
||||||
public Object[] toArray(Object[]a)
|
public Object[] toArray(Object[] a)
|
||||||
{
|
{
|
||||||
int size = size();
|
int size = size();
|
||||||
if (a.length < size)
|
if (a.length < size)
|
||||||
{
|
a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
|
||||||
a = (Object[])Array.newInstance(a.getClass().getComponentType(),
|
size);
|
||||||
size);
|
else if (a.length > size)
|
||||||
}
|
a[size] = null;
|
||||||
|
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
for (int pos = 0; pos < size; pos++)
|
for (int pos = 0; pos < size; pos++)
|
||||||
{
|
a[pos] = itr.next();
|
||||||
a[pos] = itr.next();
|
|
||||||
}
|
|
||||||
if (a.length > size)
|
|
||||||
{
|
|
||||||
a[size] = null;
|
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,15 +411,41 @@ public abstract class AbstractCollection implements Collection
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
|
||||||
StringBuffer r = new StringBuffer("[");
|
StringBuffer r = new StringBuffer("[");
|
||||||
for (int pos = 0; pos < size; pos++)
|
for (int pos = size(); pos > 0; pos--)
|
||||||
{
|
{
|
||||||
r.append(itr.next());
|
r.append(itr.next());
|
||||||
if (pos < size - 1)
|
if (pos > 1)
|
||||||
r.append(", ");
|
r.append(", ");
|
||||||
}
|
}
|
||||||
r.append("]");
|
r.append("]");
|
||||||
return r.toString();
|
return r.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two objects according to Collection semantics.
|
||||||
|
*
|
||||||
|
* @param o1 the first object
|
||||||
|
* @param o2 the second object
|
||||||
|
* @return o1 == null ? o2 == null : o1.equals(o2)
|
||||||
|
*/
|
||||||
|
// Package visible for use throughout java.util.
|
||||||
|
// It may be inlined since it is final.
|
||||||
|
static final boolean equals(Object o1, Object o2)
|
||||||
|
{
|
||||||
|
return o1 == null ? o2 == null : o1.equals(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash an object according to Collection semantics.
|
||||||
|
*
|
||||||
|
* @param o the object to hash
|
||||||
|
* @return o1 == null ? 0 : o1.hashCode()
|
||||||
|
*/
|
||||||
|
// Package visible for use throughout java.util.
|
||||||
|
// It may be inlined since it is final.
|
||||||
|
static final int hashCode(Object o)
|
||||||
|
{
|
||||||
|
return o == null ? 0 : o.hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractMap.java -- Abstract implementation of most of Map
|
/* AbstractMap.java -- Abstract implementation of most of Map
|
||||||
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -25,22 +25,71 @@ This exception does not however invalidate any other reasons why the
|
||||||
executable file might be covered by the GNU General Public License. */
|
executable file might be covered by the GNU General Public License. */
|
||||||
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// comments
|
|
||||||
// test suite
|
|
||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract implementation of Map to make it easier to create your own
|
||||||
|
* implementations. In order to create an unmodifiable Map, subclass
|
||||||
|
* AbstractMap and implement the <code>entrySet</code> (usually via an
|
||||||
|
* AbstractSet). To make it modifiable, also implement <code>put</code>,
|
||||||
|
* and have <code>entrySet().iterator()</code> support <code>remove</code>.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* It is recommended that classes which extend this support at least the
|
||||||
|
* no-argument constructor, and a constructor which accepts another Map.
|
||||||
|
* Further methods in this class may be overridden if you have a more
|
||||||
|
* efficient implementation.
|
||||||
|
*
|
||||||
|
* @author Original author unknown
|
||||||
|
* @author Bryce McKinlay
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Map
|
||||||
|
* @see Collection
|
||||||
|
* @see HashMap
|
||||||
|
* @see LinkedHashMap
|
||||||
|
* @see TreeMap
|
||||||
|
* @see WeakHashMap
|
||||||
|
* @see IdentityHashMap
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
|
*/
|
||||||
public abstract class AbstractMap implements Map
|
public abstract class AbstractMap implements Map
|
||||||
{
|
{
|
||||||
|
/** An "enum" of iterator types. */
|
||||||
|
// Package visible for use by subclasses.
|
||||||
|
static final int KEYS = 0,
|
||||||
|
VALUES = 1,
|
||||||
|
ENTRIES = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all entries from this Map. This default implementation calls
|
* The cache for {@link #keySet()}.
|
||||||
* entrySet().clear().
|
*/
|
||||||
|
// Package visible for use by subclasses.
|
||||||
|
Set keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache for {@link #values()}.
|
||||||
|
*/
|
||||||
|
// Package visible for use by subclasses.
|
||||||
|
Collection values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main constructor, for use by subclasses.
|
||||||
|
*/
|
||||||
|
protected AbstractMap()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all entries from this Map (optional operation). This default
|
||||||
|
* implementation calls entrySet().clear(). NOTE: If the entry set does
|
||||||
|
* not permit clearing, then this will fail, too. Subclasses often
|
||||||
|
* override this for efficiency. Your implementation of entrySet() should
|
||||||
|
* not call <code>AbstractMap.clear</code> unless you want an infinite loop.
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException
|
* @throws UnsupportedOperationException if <code>entrySet().clear()</code>
|
||||||
* @specnote The JCL book claims that this implementation always throws
|
* does not support clearing.
|
||||||
* UnsupportedOperationException, while the online docs claim it
|
* @see Set#clear()
|
||||||
* calls entrySet().clear(). We take the later to be correct.
|
|
||||||
*/
|
*/
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
|
@ -48,246 +97,414 @@ public abstract class AbstractMap implements Map
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a shallow copy of this Map, no keys or values are copied.
|
* Create a shallow copy of this Map, no keys or values are copied. The
|
||||||
|
* default implementation simply calls <code>super.clone()</code>.
|
||||||
|
*
|
||||||
|
* @return the shallow clone
|
||||||
|
* @throws CloneNotSupportedException if a subclass is not Cloneable
|
||||||
|
* @see Cloneable
|
||||||
|
* @see Object#clone()
|
||||||
*/
|
*/
|
||||||
protected Object clone () throws CloneNotSupportedException
|
protected Object clone() throws CloneNotSupportedException
|
||||||
{
|
{
|
||||||
return super.clone ();
|
AbstractMap copy = (AbstractMap) super.clone();
|
||||||
|
// Clear out the caches; they are stale.
|
||||||
|
copy.keys = null;
|
||||||
|
copy.values = null;
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this contains a mapping for the given key. This
|
||||||
|
* implementation does a linear search, O(n), over the
|
||||||
|
* <code>entrySet()</code>, returning <code>true</code> if a match
|
||||||
|
* is found, <code>false</code> if the iteration ends. Many subclasses
|
||||||
|
* can implement this more efficiently.
|
||||||
|
*
|
||||||
|
* @param key the key to search for
|
||||||
|
* @return true if the map contains the key
|
||||||
|
* @throws NullPointerException if key is <code>null</code> but the map
|
||||||
|
* does not permit null keys
|
||||||
|
* @see #containsValue(Object)
|
||||||
|
*/
|
||||||
public boolean containsKey(Object key)
|
public boolean containsKey(Object key)
|
||||||
{
|
{
|
||||||
Object k;
|
Iterator entries = entrySet().iterator();
|
||||||
Set es = entrySet();
|
int pos = size();
|
||||||
Iterator entries = es.iterator();
|
while (--pos >= 0)
|
||||||
int size = size();
|
if (equals(key, ((Map.Entry) entries.next()).getKey()))
|
||||||
for (int pos = 0; pos < size; pos++)
|
return true;
|
||||||
{
|
|
||||||
k = ((Map.Entry) entries.next()).getKey();
|
|
||||||
if (key == null ? k == null : key.equals(k))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this contains at least one mapping with the given value.
|
||||||
|
* This implementation does a linear search, O(n), over the
|
||||||
|
* <code>entrySet()</code>, returning <code>true</code> if a match
|
||||||
|
* is found, <code>false</code> if the iteration ends. A match is
|
||||||
|
* defined as <code>(value == null ? v == null : value.equals(v))</code>
|
||||||
|
* Subclasses are unlikely to implement this more efficiently.
|
||||||
|
*
|
||||||
|
* @param value the value to search for
|
||||||
|
* @return true if the map contains the value
|
||||||
|
* @see #containsKey(Object)
|
||||||
|
*/
|
||||||
public boolean containsValue(Object value)
|
public boolean containsValue(Object value)
|
||||||
{
|
{
|
||||||
Object v;
|
Iterator entries = entrySet().iterator();
|
||||||
Set es = entrySet();
|
int pos = size();
|
||||||
Iterator entries = es.iterator();
|
while (--pos >= 0)
|
||||||
int size = size();
|
if (equals(value, ((Map.Entry) entries.next()).getValue()))
|
||||||
for (int pos = 0; pos < size; pos++)
|
return true;
|
||||||
{
|
|
||||||
v = ((Map.Entry) entries.next()).getValue();
|
|
||||||
if (value == null ? v == null : value.equals(v))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set view of the mappings in this Map. Each element in the
|
||||||
|
* set must be an implementation of Map.Entry. The set is backed by
|
||||||
|
* the map, so that changes in one show up in the other. Modifications
|
||||||
|
* made while an iterator is in progress cause undefined behavior. If
|
||||||
|
* the set supports removal, these methods must be valid:
|
||||||
|
* <code>Iterator.remove</code>, <code>Set.remove</code>,
|
||||||
|
* <code>removeAll</code>, <code>retainAll</code>, and <code>clear</code>.
|
||||||
|
* Element addition is not supported via this set.
|
||||||
|
*
|
||||||
|
* @return the entry set
|
||||||
|
* @see Map.Entry
|
||||||
|
*/
|
||||||
public abstract Set entrySet();
|
public abstract Set entrySet();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the specified object with this map for equality. Returns
|
||||||
|
* <code>true</code> if the other object is a Map with the same mappings,
|
||||||
|
* that is,<br>
|
||||||
|
* <code>o instanceof Map && entrySet().equals(((Map) o).entrySet();</code>
|
||||||
|
*
|
||||||
|
* @param o the object to be compared
|
||||||
|
* @return true if the object equals this map
|
||||||
|
* @see Set#equals(Object)
|
||||||
|
*/
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (o == this)
|
return (o == this ||
|
||||||
return true;
|
(o instanceof Map &&
|
||||||
if (!(o instanceof Map))
|
entrySet().equals(((Map) o).entrySet())));
|
||||||
return false;
|
|
||||||
|
|
||||||
Map m = (Map) o;
|
|
||||||
Set s = m.entrySet();
|
|
||||||
Iterator itr = entrySet().iterator();
|
|
||||||
int size = size();
|
|
||||||
|
|
||||||
if (m.size() != size)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int pos = 0; pos < size; pos++)
|
|
||||||
{
|
|
||||||
if (!s.contains(itr.next()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value mapped by the given key. Returns <code>null</code> if
|
||||||
|
* there is no mapping. However, in Maps that accept null values, you
|
||||||
|
* must rely on <code>containsKey</code> to determine if a mapping exists.
|
||||||
|
* This iteration takes linear time, searching entrySet().iterator() of
|
||||||
|
* the key. Many implementations override this method.
|
||||||
|
*
|
||||||
|
* @param key the key to look up
|
||||||
|
* @return the value associated with the key, or null if key not in map
|
||||||
|
* @throws NullPointerException if this map does not accept null keys
|
||||||
|
* @see #containsKey(Object)
|
||||||
|
*/
|
||||||
public Object get(Object key)
|
public Object get(Object key)
|
||||||
{
|
{
|
||||||
Set s = entrySet();
|
Iterator entries = entrySet().iterator();
|
||||||
Iterator entries = s.iterator();
|
int pos = size();
|
||||||
int size = size();
|
while (--pos >= 0)
|
||||||
|
|
||||||
for (int pos = 0; pos < size; pos++)
|
|
||||||
{
|
{
|
||||||
Map.Entry entry = (Map.Entry) entries.next();
|
Map.Entry entry = (Map.Entry) entries.next();
|
||||||
Object k = entry.getKey();
|
if (equals(key, entry.getKey()))
|
||||||
if (key == null ? k == null : key.equals(k))
|
return entry.getValue();
|
||||||
return entry.getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash code for this map. As defined in Map, this is the sum
|
||||||
|
* of all hashcodes for each Map.Entry object in entrySet, or basically
|
||||||
|
* entrySet().hashCode().
|
||||||
|
*
|
||||||
|
* @return the hash code
|
||||||
|
* @see Map.Entry#hashCode()
|
||||||
|
* @see Set#hashCode()
|
||||||
|
*/
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
int hashcode = 0;
|
return entrySet().hashCode();
|
||||||
Iterator itr = entrySet().iterator();
|
|
||||||
int size = size();
|
|
||||||
for (int pos = 0; pos < size; pos++)
|
|
||||||
{
|
|
||||||
hashcode += itr.next().hashCode();
|
|
||||||
}
|
|
||||||
return hashcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the map contains no mappings. This is implemented by
|
||||||
|
* <code>size() == 0</code>.
|
||||||
|
*
|
||||||
|
* @return true if the map is empty
|
||||||
|
* @see #size()
|
||||||
|
*/
|
||||||
public boolean isEmpty()
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set view of this map's keys. The set is backed by the map,
|
||||||
|
* so changes in one show up in the other. Modifications while an iteration
|
||||||
|
* is in progress produce undefined behavior. The set supports removal
|
||||||
|
* if entrySet() does, but does not support element addition.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This implementation creates an AbstractSet, where the iterator wraps
|
||||||
|
* the entrySet iterator, size defers to the Map's size, and contains
|
||||||
|
* defers to the Map's containsKey. The set is created on first use, and
|
||||||
|
* returned on subsequent uses, although since no synchronization occurs,
|
||||||
|
* there is a slight possibility of creating two sets.
|
||||||
|
*
|
||||||
|
* @return a Set view of the keys
|
||||||
|
* @see Set#iterator()
|
||||||
|
* @see #size()
|
||||||
|
* @see #containsKey(Object)
|
||||||
|
* @see #values()
|
||||||
|
*/
|
||||||
public Set keySet()
|
public Set keySet()
|
||||||
{
|
{
|
||||||
if (this.keySet == null)
|
if (keys == null)
|
||||||
|
keys = new AbstractSet()
|
||||||
{
|
{
|
||||||
this.keySet = new AbstractSet()
|
public int size()
|
||||||
{
|
{
|
||||||
public int size()
|
return AbstractMap.this.size();
|
||||||
{
|
}
|
||||||
return AbstractMap.this.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Object key)
|
public boolean contains(Object key)
|
||||||
{
|
{
|
||||||
return AbstractMap.this.containsKey(key);
|
return containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return new Iterator()
|
return new Iterator()
|
||||||
{
|
{
|
||||||
Iterator map_iterator = AbstractMap.this.entrySet().iterator();
|
private final Iterator map_iterator = entrySet().iterator();
|
||||||
|
|
||||||
public boolean hasNext()
|
public boolean hasNext()
|
||||||
{
|
{
|
||||||
return map_iterator.hasNext();
|
return map_iterator.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next()
|
public Object next()
|
||||||
{
|
{
|
||||||
return ((Map.Entry) map_iterator.next()).getKey();
|
return ((Map.Entry) map_iterator.next()).getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove()
|
public void remove()
|
||||||
{
|
{
|
||||||
map_iterator.remove();
|
map_iterator.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
return keys;
|
||||||
|
|
||||||
return this.keySet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates the given key to the given value (optional operation). If the
|
||||||
|
* map already contains the key, its value is replaced. This implementation
|
||||||
|
* simply throws an UnsupportedOperationException. Be aware that in a map
|
||||||
|
* that permits <code>null</code> values, a null return does not always
|
||||||
|
* imply that the mapping was created.
|
||||||
|
*
|
||||||
|
* @param key the key to map
|
||||||
|
* @param value the value to be mapped
|
||||||
|
* @return the previous value of the key, or null if there was no mapping
|
||||||
|
* @throws UnsupportedOperationException if the operation is not supported
|
||||||
|
* @throws ClassCastException if the key or value is of the wrong type
|
||||||
|
* @throws IllegalArgumentException if something about this key or value
|
||||||
|
* prevents it from existing in this map
|
||||||
|
* @throws NullPointerException if the map forbids null keys or values
|
||||||
|
* @see #containsKey(Object)
|
||||||
|
*/
|
||||||
public Object put(Object key, Object value)
|
public Object put(Object key, Object value)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all entries of the given map to this one (optional operation). If
|
||||||
|
* the map already contains a key, its value is replaced. This implementation
|
||||||
|
* simply iterates over the map's entrySet(), calling <code>put</code>,
|
||||||
|
* so it is not supported if puts are not.
|
||||||
|
*
|
||||||
|
* @param m the mapping to load into this map
|
||||||
|
* @throws UnsupportedOperationException if the operation is not supported
|
||||||
|
* @throws ClassCastException if a key or value is of the wrong type
|
||||||
|
* @throws IllegalArgumentException if something about a key or value
|
||||||
|
* prevents it from existing in this map
|
||||||
|
* @throws NullPointerException if the map forbids null keys or values, or
|
||||||
|
* if <code>m</code> is null.
|
||||||
|
* @see #put(Object, Object)
|
||||||
|
*/
|
||||||
public void putAll(Map m)
|
public void putAll(Map m)
|
||||||
{
|
{
|
||||||
Map.Entry entry;
|
|
||||||
Iterator entries = m.entrySet().iterator();
|
Iterator entries = m.entrySet().iterator();
|
||||||
int size = m.size();
|
int pos = size();
|
||||||
|
while (--pos >= 0)
|
||||||
for (int pos = 0; pos < size; pos++)
|
|
||||||
{
|
{
|
||||||
entry = (Map.Entry) entries.next();
|
Map.Entry entry = (Map.Entry) entries.next();
|
||||||
put(entry.getKey(), entry.getValue());
|
put(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the mapping for this key if present (optional operation). This
|
||||||
|
* implementation iterates over the entrySet searching for a matching
|
||||||
|
* key, at which point it calls the iterator's <code>remove</code> method.
|
||||||
|
* It returns the result of <code>getValue()</code> on the entry, if found,
|
||||||
|
* or null if no entry is found. Note that maps which permit null values
|
||||||
|
* may also return null if the key was removed. If the entrySet does not
|
||||||
|
* support removal, this will also fail. This is O(n), so many
|
||||||
|
* implementations override it for efficiency.
|
||||||
|
*
|
||||||
|
* @param key the key to remove
|
||||||
|
* @return the value the key mapped to, or null if not present
|
||||||
|
* @throws UnsupportedOperationException if deletion is unsupported
|
||||||
|
* @see Iterator#remove()
|
||||||
|
*/
|
||||||
public Object remove(Object key)
|
public Object remove(Object key)
|
||||||
{
|
{
|
||||||
Iterator entries = entrySet().iterator();
|
Iterator entries = entrySet().iterator();
|
||||||
int size = size();
|
int pos = size();
|
||||||
|
while (--pos >= 0)
|
||||||
for (int pos = 0; pos < size; pos++)
|
|
||||||
{
|
{
|
||||||
Map.Entry entry = (Map.Entry) entries.next();
|
Map.Entry entry = (Map.Entry) entries.next();
|
||||||
Object k = entry.getKey();
|
if (equals(key, entry.getKey()))
|
||||||
if (key == null ? k == null : key.equals(k))
|
{
|
||||||
{
|
// Must get the value before we remove it from iterator.
|
||||||
Object value = entry.getValue();
|
Object r = entry.getValue();
|
||||||
entries.remove();
|
entries.remove();
|
||||||
return value;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of key-value mappings in the map. If there are more
|
||||||
|
* than Integer.MAX_VALUE mappings, return Integer.MAX_VALUE. This is
|
||||||
|
* implemented as <code>entrySet().size()</code>.
|
||||||
|
*
|
||||||
|
* @return the number of mappings
|
||||||
|
* @see Set#size()
|
||||||
|
*/
|
||||||
public int size()
|
public int size()
|
||||||
{
|
{
|
||||||
return entrySet().size();
|
return entrySet().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a String representation of this map. This is a listing of the
|
||||||
|
* map entries (which are specified in Map.Entry as being
|
||||||
|
* <code>getKey() + "=" + getValue()</code>), separated by a comma and
|
||||||
|
* space (", "), and surrounded by braces ('{' and '}'). This implementation
|
||||||
|
* uses a StringBuffer and iterates over the entrySet to build the String.
|
||||||
|
* Note that this can fail with an exception if underlying keys or
|
||||||
|
* values complete abruptly in toString().
|
||||||
|
*
|
||||||
|
* @return a String representation
|
||||||
|
* @see Map.Entry#toString()
|
||||||
|
*/
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
Iterator entries = entrySet().iterator();
|
Iterator entries = entrySet().iterator();
|
||||||
int size = size();
|
|
||||||
StringBuffer r = new StringBuffer("{");
|
StringBuffer r = new StringBuffer("{");
|
||||||
for (int pos = 0; pos < size; pos++)
|
for (int pos = size(); pos > 0; pos--)
|
||||||
{
|
{
|
||||||
// Append the toString value of the entries rather than calling
|
// Append the toString value of the entries rather than calling
|
||||||
// getKey/getValue. This is more efficient and it matches the JDK
|
// getKey/getValue. This is more efficient and it matches the JDK
|
||||||
// behaviour.
|
// behaviour.
|
||||||
r.append(entries.next());
|
r.append(entries.next());
|
||||||
if (pos < size - 1)
|
if (pos > 1)
|
||||||
r.append(", ");
|
r.append(", ");
|
||||||
}
|
}
|
||||||
r.append("}");
|
r.append("}");
|
||||||
return r.toString();
|
return r.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a collection or bag view of this map's values. The collection
|
||||||
|
* is backed by the map, so changes in one show up in the other.
|
||||||
|
* Modifications while an iteration is in progress produce undefined
|
||||||
|
* behavior. The collection supports removal if entrySet() does, but
|
||||||
|
* does not support element addition.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This implementation creates an AbstractCollection, where the iterator
|
||||||
|
* wraps the entrySet iterator, size defers to the Map's size, and contains
|
||||||
|
* defers to the Map's containsValue. The collection is created on first
|
||||||
|
* use, and returned on subsequent uses, although since no synchronization
|
||||||
|
* occurs, there is a slight possibility of creating two collections.
|
||||||
|
*
|
||||||
|
* @return a Collection view of the values
|
||||||
|
* @see Collection#iterator()
|
||||||
|
* @see #size()
|
||||||
|
* @see #containsValue(Object)
|
||||||
|
* @see #keySet()
|
||||||
|
*/
|
||||||
public Collection values()
|
public Collection values()
|
||||||
{
|
{
|
||||||
if (this.valueCollection == null)
|
if (values == null)
|
||||||
|
values = new AbstractCollection()
|
||||||
{
|
{
|
||||||
this.valueCollection = new AbstractCollection()
|
public int size()
|
||||||
{
|
{
|
||||||
public int size()
|
return AbstractMap.this.size();
|
||||||
{
|
}
|
||||||
return AbstractMap.this.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return new Iterator()
|
return new Iterator()
|
||||||
{
|
{
|
||||||
Iterator map_iterator = AbstractMap.this.entrySet().iterator();
|
private final Iterator map_iterator = entrySet().iterator();
|
||||||
|
|
||||||
public boolean hasNext()
|
public boolean hasNext()
|
||||||
{
|
{
|
||||||
return map_iterator.hasNext();
|
return map_iterator.hasNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next()
|
public Object next()
|
||||||
{
|
{
|
||||||
return ((Map.Entry) map_iterator.next()).getValue();
|
return ((Map.Entry) map_iterator.next()).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove()
|
public void remove()
|
||||||
{
|
{
|
||||||
map_iterator.remove();
|
map_iterator.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
return values;
|
||||||
|
|
||||||
return this.valueCollection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection valueCollection = null;
|
/**
|
||||||
private Set keySet = null;
|
* Compare two objects according to Collection semantics.
|
||||||
|
*
|
||||||
|
* @param o1 the first object
|
||||||
|
* @param o2 the second object
|
||||||
|
* @return o1 == null ? o2 == null : o1.equals(o2)
|
||||||
|
*/
|
||||||
|
// Package visible for use throughout java.util.
|
||||||
|
// It may be inlined since it is final.
|
||||||
|
static final boolean equals(Object o1, Object o2)
|
||||||
|
{
|
||||||
|
return o1 == null ? o2 == null : o1.equals(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash an object according to Collection semantics.
|
||||||
|
*
|
||||||
|
* @param o the object to hash
|
||||||
|
* @return o1 == null ? 0 : o1.hashCode()
|
||||||
|
*/
|
||||||
|
// Package visible for use throughout java.util.
|
||||||
|
// It may be inlined since it is final.
|
||||||
|
static final int hashCode(Object o)
|
||||||
|
{
|
||||||
|
return o == null ? 0 : o.hashCode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractSequentialList.java -- List implementation for sequential access
|
/* AbstractSequentialList.java -- List implementation for sequential access
|
||||||
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -25,100 +25,192 @@ This exception does not however invalidate any other reasons why the
|
||||||
executable file might be covered by the GNU General Public License. */
|
executable file might be covered by the GNU General Public License. */
|
||||||
|
|
||||||
|
|
||||||
// TO DO:
|
|
||||||
// ~ Lots of doc comments still missing.
|
|
||||||
// ~ The class comment should include a description of what should be overridden
|
|
||||||
// to provide what features, as should the listIterator comment.
|
|
||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract superclass to make it easier to implement the List interface when
|
* Abstract superclass to make it easier to implement the List interface when
|
||||||
* backed by a sequential-access store, such as a linked list.
|
* backed by a sequential-access store, such as a linked list. For random
|
||||||
|
* access data, use AbstractList. This class implements the random access
|
||||||
|
* methods (<code>get</code>, <code>set</code>, <code>add</code>, and
|
||||||
|
* <code>remove</code>) atop the list iterator, opposite of AbstractList's
|
||||||
|
* approach of implementing the iterator atop random access.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* To implement a list, you need an implementation for <code>size()</code>
|
||||||
|
* and <code>listIterator</code>. With just <code>hasNext</code>,
|
||||||
|
* <code>next</code>, <code>hasPrevious</code>, <code>previous</code>,
|
||||||
|
* <code>nextIndex</code>, and <code>previousIndex</code>, you have an
|
||||||
|
* unmodifiable list. For a modifiable one, add <code>set</code>, and for
|
||||||
|
* a variable-size list, add <code>add</code> and <code>remove</code>.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The programmer should provide a no-argument constructor, and one that
|
||||||
|
* accepts another Collection, as recommended by the Collection interface.
|
||||||
|
* Unfortunately, there is no way to enforce this in Java.
|
||||||
|
*
|
||||||
|
* @author Original author unknown
|
||||||
|
* @author Bryce McKinlay
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see List
|
||||||
|
* @see AbstractList
|
||||||
|
* @see AbstractCollection
|
||||||
|
* @see ListIterator
|
||||||
|
* @see LinkedList
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSequentialList extends AbstractList
|
public abstract class AbstractSequentialList extends AbstractList
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The main constructor, for use by subclasses.
|
||||||
|
*/
|
||||||
|
protected AbstractSequentialList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a ListIterator over the list, starting from position index.
|
* Returns a ListIterator over the list, starting from position index.
|
||||||
* Subclasses must provide an implementation of this method.
|
* Subclasses must provide an implementation of this method.
|
||||||
*
|
*
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size()
|
* @param index the starting position of the list
|
||||||
|
* @return the list iterator
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||||
*/
|
*/
|
||||||
public abstract ListIterator listIterator(int index);
|
public abstract ListIterator listIterator(int index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an element to the list at a given index. This implementation obtains a
|
* Insert an element into the list at a given position (optional operation).
|
||||||
* ListIterator positioned at the specified index, and then adds the element
|
* This shifts all existing elements from that position to the end one
|
||||||
* using the ListIterator's add method.
|
* index to the right. This version of add has no return, since it is
|
||||||
|
* assumed to always succeed if there is no exception. This iteration
|
||||||
|
* uses listIterator(index).add(o).
|
||||||
*
|
*
|
||||||
* @param index the position to add the element
|
* @param index the location to insert the item
|
||||||
* @param o the element to insert
|
* @param o the object to insert
|
||||||
* @exception IndexOutOfBoundsException if index < 0 || index > size()
|
* @throws UnsupportedOperationException if this list does not support the
|
||||||
* @exception UnsupportedOperationException if the iterator returned by
|
* add operation
|
||||||
* listIterator(index) does not support the add method.
|
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||||
|
* @throws ClassCastException if o cannot be added to this list due to its
|
||||||
|
* type
|
||||||
|
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||||
|
* some other reason
|
||||||
*/
|
*/
|
||||||
public void add(int index, Object o)
|
public void add(int index, Object o)
|
||||||
{
|
{
|
||||||
ListIterator i = listIterator(index);
|
listIterator(index).add(o);
|
||||||
i.add(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @specnote The spec in the JDK1.3 online docs is wrong. The implementation
|
* Insert the contents of a collection into the list at a given position
|
||||||
* should not call next() to skip over new elements as they are
|
* (optional operation). Shift all elements at that position to the right
|
||||||
* added, because iterator.add() should add new elements BEFORE
|
* by the number of elements inserted. This operation is undefined if
|
||||||
* the cursor.
|
* this list is modified during the operation (for example, if you try
|
||||||
|
* to insert a list into itself).
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* This implementation grabs listIterator(index), then proceeds to use add
|
||||||
|
* for each element returned by c's iterator. Sun's online specs are wrong,
|
||||||
|
* claiming that this also calls next(): listIterator.add() correctly
|
||||||
|
* skips the added element.
|
||||||
|
*
|
||||||
|
* @param index the location to insert the collection
|
||||||
|
* @param c the collection to insert
|
||||||
|
* @return true if the list was modified by this action, that is, if c is
|
||||||
|
* non-empty
|
||||||
|
* @throws UnsupportedOperationException if this list does not support the
|
||||||
|
* addAll operation
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||||
|
* @throws ClassCastException if some element of c cannot be added to this
|
||||||
|
* list due to its type
|
||||||
|
* @throws IllegalArgumentException if some element of c cannot be added
|
||||||
|
* to this list for some other reason
|
||||||
|
* @throws NullPointerException if the specified collection is null
|
||||||
|
* @see #add(int, Object)
|
||||||
*/
|
*/
|
||||||
public boolean addAll(int index, Collection c)
|
public boolean addAll(int index, Collection c)
|
||||||
{
|
{
|
||||||
boolean modified = false;
|
|
||||||
Iterator ci = c.iterator();
|
Iterator ci = c.iterator();
|
||||||
int size = c.size();
|
int size = c.size();
|
||||||
ListIterator i = listIterator(index);
|
ListIterator i = listIterator(index);
|
||||||
for (int pos = 0; pos < size; pos++)
|
for (int pos = size; pos > 0; pos--)
|
||||||
{
|
i.add(ci.next());
|
||||||
i.add(ci.next());
|
return size > 0;
|
||||||
}
|
|
||||||
return (size > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object get(int index)
|
|
||||||
{
|
|
||||||
ListIterator i = listIterator(index);
|
|
||||||
if (index < 0 || index > size())
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size());
|
|
||||||
return i.next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an Iterator over this List. This implementation returns
|
* Get the element at a given index in this list. This implementation
|
||||||
* listIterator().
|
* returns listIterator(index).next().
|
||||||
*
|
*
|
||||||
* @return an Iterator over this List
|
* @param index the index of the element to be returned
|
||||||
|
* @return the element at index index in this list
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||||
|
*/
|
||||||
|
public Object get(int index)
|
||||||
|
{
|
||||||
|
// This is a legal listIterator position, but an illegal get.
|
||||||
|
if (index == size())
|
||||||
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
|
||||||
|
+ size());
|
||||||
|
return listIterator(index).next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain an Iterator over this list, whose sequence is the list order. This
|
||||||
|
* implementation returns listIterator().
|
||||||
|
*
|
||||||
|
* @return an Iterator over the elements of this list, in order
|
||||||
*/
|
*/
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return listIterator();
|
return listIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the element at a given position in this list (optional operation).
|
||||||
|
* Shifts all remaining elements to the left to fill the gap. This
|
||||||
|
* implementation uses listIterator(index) and ListIterator.remove().
|
||||||
|
*
|
||||||
|
* @param index the position within the list of the object to remove
|
||||||
|
* @return the object that was removed
|
||||||
|
* @throws UnsupportedOperationException if this list does not support the
|
||||||
|
* remove operation
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||||
|
*/
|
||||||
public Object remove(int index)
|
public Object remove(int index)
|
||||||
{
|
{
|
||||||
|
// This is a legal listIterator position, but an illegal remove.
|
||||||
|
if (index == size())
|
||||||
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
|
||||||
|
+ size());
|
||||||
ListIterator i = listIterator(index);
|
ListIterator i = listIterator(index);
|
||||||
if (index < 0 || index > size())
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size());
|
|
||||||
Object removed = i.next();
|
Object removed = i.next();
|
||||||
i.remove();
|
i.remove();
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace an element of this list with another object (optional operation).
|
||||||
|
* This implementation uses listIterator(index) and ListIterator.set(o).
|
||||||
|
*
|
||||||
|
* @param index the position within this list of the element to be replaced
|
||||||
|
* @param o the object to replace it with
|
||||||
|
* @return the object that was replaced
|
||||||
|
* @throws UnsupportedOperationException if this list does not support the
|
||||||
|
* set operation
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||||
|
* @throws ClassCastException if o cannot be added to this list due to its
|
||||||
|
* type
|
||||||
|
* @throws IllegalArgumentException if o cannot be added to this list for
|
||||||
|
* some other reason
|
||||||
|
*/
|
||||||
public Object set(int index, Object o)
|
public Object set(int index, Object o)
|
||||||
{
|
{
|
||||||
|
// This is a legal listIterator position, but an illegal set.
|
||||||
|
if (index == size())
|
||||||
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:"
|
||||||
|
+ size());
|
||||||
ListIterator i = listIterator(index);
|
ListIterator i = listIterator(index);
|
||||||
if (index < 0 || index > size())
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size());
|
|
||||||
Object old = i.next();
|
Object old = i.next();
|
||||||
i.set(o);
|
i.set(o);
|
||||||
return old;
|
return old;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* AbstractSet.java -- Abstract implementation of most of Set
|
/* AbstractSet.java -- Abstract implementation of most of Set
|
||||||
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -35,9 +35,27 @@ package java.util;
|
||||||
* on them - specifically, no element may be in the set more than once). This
|
* on them - specifically, no element may be in the set more than once). This
|
||||||
* class simply provides implementations of equals() and hashCode() to fulfil
|
* class simply provides implementations of equals() and hashCode() to fulfil
|
||||||
* the requirements placed on them by the Set interface.
|
* the requirements placed on them by the Set interface.
|
||||||
|
*
|
||||||
|
* @author Original author unknown
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see AbstractCollection
|
||||||
|
* @see Set
|
||||||
|
* @see HashSet
|
||||||
|
* @see TreeSet
|
||||||
|
* @see LinkedHashSet
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSet extends AbstractCollection implements Set
|
public abstract class AbstractSet extends AbstractCollection implements Set
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The main constructor, for use by subclasses.
|
||||||
|
*/
|
||||||
|
protected AbstractSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether the given object is equal to this Set. This implementation
|
* Tests whether the given object is equal to this Set. This implementation
|
||||||
* first checks whether this set <em>is</em> the given object, and returns
|
* first checks whether this set <em>is</em> the given object, and returns
|
||||||
|
@ -50,12 +68,9 @@ public abstract class AbstractSet extends AbstractCollection implements Set
|
||||||
*/
|
*/
|
||||||
public boolean equals(Object o)
|
public boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (o == this)
|
return (o == this ||
|
||||||
return true;
|
(o instanceof Set && ((Set) o).size() == size()
|
||||||
else if (o instanceof Set && ((Set) o).size() == size())
|
&& containsAll((Collection) o)));
|
||||||
return containsAll((Collection) o);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,14 +84,45 @@ public abstract class AbstractSet extends AbstractCollection implements Set
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
Iterator itr = iterator();
|
Iterator itr = iterator();
|
||||||
int size = size();
|
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
for (int pos = 0; pos < size; pos++)
|
int pos = size();
|
||||||
{
|
while (--pos >= 0)
|
||||||
Object obj = itr.next();
|
hash += hashCode(itr.next());
|
||||||
if (obj != null)
|
|
||||||
hash += obj.hashCode();
|
|
||||||
}
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes from this set all elements in the given collection (optional
|
||||||
|
* operation). This implementation uses <code>size()</code> to determine
|
||||||
|
* the smaller collection. Then, if this set is smaller, it iterates
|
||||||
|
* over the set, calling Iterator.remove if the collection contains
|
||||||
|
* the element. If this set is larger, it iterates over the collection,
|
||||||
|
* calling Set.remove for all elements in the collection. Note that
|
||||||
|
* this operation will fail if a remove methods is not supported.
|
||||||
|
*
|
||||||
|
* @param c the collection of elements to remove
|
||||||
|
* @return true if the set was modified as a result
|
||||||
|
* @throws UnsupportedOperationException if remove is not supported
|
||||||
|
* @throws NullPointerException if the collection is null
|
||||||
|
* @see AbstractCollection#remove(Object)
|
||||||
|
* @see Collection#contains(Object)
|
||||||
|
* @see Iterator#remove()
|
||||||
|
*/
|
||||||
|
public boolean removeAll(Collection c)
|
||||||
|
{
|
||||||
|
int oldsize = size();
|
||||||
|
int count = c.size();
|
||||||
|
Iterator i;
|
||||||
|
if (oldsize < count)
|
||||||
|
{
|
||||||
|
for (i = iterator(), count = oldsize; count > 0; count--)
|
||||||
|
if (c.contains(i.next()))
|
||||||
|
i.remove();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (i = c.iterator(); count > 0; count--)
|
||||||
|
remove(i.next());
|
||||||
|
return oldsize != size();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
|
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed
|
||||||
implementation of the List interface
|
implementation of the List interface
|
||||||
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -35,112 +35,143 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array-backed implementation of the List interface. ArrayList
|
* An array-backed implementation of the List interface. This implements
|
||||||
* performs well on simple tasks: random access into a list, appending
|
* all optional list operations, and permits null elements, so that it is
|
||||||
* to or removing from the end of a list, checking the size, &c.
|
* better than Vector, which it replaces. Random access is roughly constant
|
||||||
|
* time, and iteration is roughly linear time, so it is nice and fast, with
|
||||||
|
* less overhead than a LinkedList.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* @author Jon A. Zeppieri
|
* Each list has a capacity, and as the array reaches that capacity it
|
||||||
* @see java.util.AbstractList
|
* is automatically transferred to a larger array. You also have access to
|
||||||
* @see java.util.List
|
* ensureCapacity and trimToSize to control the backing array's size, avoiding
|
||||||
|
* reallocation or wasted memory.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* ArrayList is not synchronized, so if you need multi-threaded access,
|
||||||
|
* consider using:<br>
|
||||||
|
* <code>List l = Collections.synchronizedList(new ArrayList(...));</code>
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
* modification, except for <code>remove()</code> called on the iterator
|
||||||
|
* itself, cause the iterator to throw a
|
||||||
|
* {@link ConcurrentModificationException} rather than exhibit
|
||||||
|
* non-deterministic behavior.
|
||||||
|
*
|
||||||
|
* @author Jon A. Zeppieri
|
||||||
|
* @author Bryce McKinlay
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see List
|
||||||
|
* @see LinkedList
|
||||||
|
* @see Vector
|
||||||
|
* @see Collections#synchronizedList(List)
|
||||||
|
* @see AbstractList
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class ArrayList extends AbstractList
|
public class ArrayList extends AbstractList
|
||||||
implements List, Cloneable, Serializable
|
implements List, RandomAccess, Cloneable, Serializable
|
||||||
{
|
{
|
||||||
/** the default capacity for new ArrayLists */
|
/**
|
||||||
|
* Compatible with JDK 1.2
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 8683452581122892189L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default capacity for new ArrayLists.
|
||||||
|
*/
|
||||||
private static final int DEFAULT_CAPACITY = 16;
|
private static final int DEFAULT_CAPACITY = 16;
|
||||||
|
|
||||||
/** the number of elements in this list */
|
/**
|
||||||
int size;
|
* The number of elements in this list.
|
||||||
|
* @serial the list size
|
||||||
|
*/
|
||||||
|
private int size;
|
||||||
|
|
||||||
/** where the data is stored */
|
/**
|
||||||
transient Object[] data;
|
* Where the data is stored.
|
||||||
|
*/
|
||||||
|
private transient Object[] data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ArrayList with the supplied initial capacity.
|
* Construct a new ArrayList with the supplied initial capacity.
|
||||||
*
|
*
|
||||||
* @param capacity Initial capacity of this ArrayList
|
* @param capacity initial capacity of this ArrayList
|
||||||
|
* @throws IllegalArgumentException if capacity is negative
|
||||||
*/
|
*/
|
||||||
public ArrayList(int capacity)
|
public ArrayList(int capacity)
|
||||||
{
|
{
|
||||||
|
// Must explicitly check, to get correct exception.
|
||||||
|
if (capacity < 0)
|
||||||
|
throw new IllegalArgumentException();
|
||||||
data = new Object[capacity];
|
data = new Object[capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ArrayList with the default capcity
|
* Construct a new ArrayList with the default capcity (16).
|
||||||
*/
|
*/
|
||||||
public ArrayList()
|
public ArrayList()
|
||||||
{
|
{
|
||||||
this(DEFAULT_CAPACITY);
|
this(DEFAULT_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ArrayList, and initialize it with the elements
|
* Construct a new ArrayList, and initialize it with the elements
|
||||||
* in the supplied Collection; Sun specs say that the initial
|
* in the supplied Collection. The initial capacity is 110% of the
|
||||||
* capacity is 110% of the Collection's size.
|
* Collection's size.
|
||||||
*
|
*
|
||||||
* @param c the collection whose elements will initialize this list
|
* @param c the collection whose elements will initialize this list
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
*/
|
*/
|
||||||
public ArrayList(Collection c)
|
public ArrayList(Collection c)
|
||||||
{
|
{
|
||||||
this((int) (c.size() * 1.1));
|
this((int) (c.size() * 1.1f));
|
||||||
addAll(c);
|
addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guarantees that this list will have at least enough capacity to
|
* Trims the capacity of this List to be equal to its size;
|
||||||
* hold minCapacity elements.
|
* a memory saver.
|
||||||
*
|
|
||||||
* @specnote This implementation will grow the list to
|
|
||||||
* max(current * 2, minCapacity) if (minCapacity > current). The JCL says
|
|
||||||
* explictly that "this method increases its capacity to minCap", while
|
|
||||||
* the JDK 1.3 online docs specify that the list will grow to at least the
|
|
||||||
* size specified.
|
|
||||||
* @param minCapacity the minimum guaranteed capacity
|
|
||||||
*/
|
*/
|
||||||
public void ensureCapacity(int minCapacity)
|
public void trimToSize()
|
||||||
{
|
{
|
||||||
Object[] newData;
|
// Not a structural change from the perspective of iterators on this list,
|
||||||
int current = data.length;
|
// so don't update modCount.
|
||||||
|
if (size != data.length)
|
||||||
if (minCapacity > current)
|
|
||||||
{
|
{
|
||||||
newData = new Object[Math.max((current * 2), minCapacity)];
|
Object[] newData = new Object[size];
|
||||||
System.arraycopy(data, 0, newData, 0, size);
|
System.arraycopy(data, 0, newData, 0, size);
|
||||||
data = newData;
|
data = newData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the supplied element to the end of this list.
|
* Guarantees that this list will have at least enough capacity to
|
||||||
|
* hold minCapacity elements. This implementation will grow the list to
|
||||||
|
* max(current * 2, minCapacity) if (minCapacity > current). The JCL says
|
||||||
|
* explictly that "this method increases its capacity to minCap", while
|
||||||
|
* the JDK 1.3 online docs specify that the list will grow to at least the
|
||||||
|
* size specified.
|
||||||
*
|
*
|
||||||
* @param e the element to be appended to this list
|
* @param minCapacity the minimum guaranteed capacity
|
||||||
*/
|
*/
|
||||||
public boolean add(Object e)
|
public void ensureCapacity(int minCapacity)
|
||||||
{
|
{
|
||||||
modCount++;
|
int current = data.length;
|
||||||
if (size == data.length)
|
|
||||||
ensureCapacity(size + 1);
|
if (minCapacity > current)
|
||||||
data[size++] = e;
|
{
|
||||||
return true;
|
Object[] newData = new Object[Math.max(current * 2, minCapacity)];
|
||||||
|
System.arraycopy(data, 0, newData, 0, size);
|
||||||
|
data = newData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the element at the user-supplied index.
|
* Returns the number of elements in this list.
|
||||||
*
|
*
|
||||||
* @param index the index of the element we are fetching
|
* @return the list size
|
||||||
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size())
|
|
||||||
*/
|
|
||||||
public Object get(int index)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= size)
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size);
|
|
||||||
return data[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of elements in this list
|
|
||||||
*/
|
*/
|
||||||
public int size()
|
public int size()
|
||||||
{
|
{
|
||||||
|
@ -148,202 +179,81 @@ public class ArrayList extends AbstractList
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the element at the user-supplied index
|
* Checks if the list is empty.
|
||||||
*
|
*
|
||||||
* @param iIndex the index of the element to be removed
|
* @return true if there are no elements
|
||||||
* @return the removed Object
|
|
||||||
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size())
|
|
||||||
*/
|
*/
|
||||||
public Object remove(int index)
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
modCount++;
|
return size == 0;
|
||||||
if (index < 0 || index > size)
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size);
|
|
||||||
Object r = data[index];
|
|
||||||
if (index != --size)
|
|
||||||
System.arraycopy(data, (index + 1), data, index, (size - index));
|
|
||||||
data[size] = null;
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all elements in the half-open interval [iFromIndex, iToIndex).
|
* Returns true iff element is in this ArrayList.
|
||||||
*
|
*
|
||||||
* @param fromIndex the first index which will be removed
|
* @param e the element whose inclusion in the List is being tested
|
||||||
* @param toIndex one greater than the last index which will be
|
* @return true if the list contains e
|
||||||
* removed
|
|
||||||
*/
|
*/
|
||||||
protected void removeRange(int fromIndex, int toIndex)
|
public boolean contains(Object e)
|
||||||
{
|
{
|
||||||
modCount++;
|
return indexOf(e) != -1;
|
||||||
if (fromIndex != toIndex)
|
|
||||||
{
|
|
||||||
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
|
|
||||||
size -= (toIndex - fromIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the supplied element at the specified index, shifting all
|
* Returns the lowest index at which element appears in this List, or
|
||||||
* elements currently at that index or higher one to the right.
|
* -1 if it does not appear.
|
||||||
*
|
*
|
||||||
* @param index the index at which the element is being added
|
* @param e the element whose inclusion in the List is being tested
|
||||||
* @param e the item being added
|
* @return the index where e was found
|
||||||
*/
|
*/
|
||||||
public void add(int index, Object e)
|
public int indexOf(Object e)
|
||||||
{
|
{
|
||||||
modCount++;
|
for (int i = 0; i < size; i++)
|
||||||
if (index < 0 || index > size)
|
if (equals(e, data[i]))
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
return i;
|
||||||
size);
|
return -1;
|
||||||
if (size == data.length)
|
|
||||||
ensureCapacity(size + 1);
|
|
||||||
if (index != size)
|
|
||||||
System.arraycopy(data, index, data, index + 1, size - index);
|
|
||||||
data[index] = e;
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add each element in the supplied Collection to this List.
|
|
||||||
*
|
|
||||||
* @param c a Collection containing elements to be
|
|
||||||
* added to this List
|
|
||||||
*/
|
|
||||||
public boolean addAll(Collection c)
|
|
||||||
{
|
|
||||||
return addAll(size, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all elements in the supplied collection, inserting them beginning
|
|
||||||
* at the specified index.
|
|
||||||
*
|
|
||||||
* @param index the index at which the elements will be inserted
|
|
||||||
* @param c the Collection containing the elements to be
|
|
||||||
* inserted
|
|
||||||
*/
|
|
||||||
public boolean addAll(int index, Collection c)
|
|
||||||
{
|
|
||||||
if (index < 0 || index > size)
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size);
|
|
||||||
modCount++;
|
|
||||||
Iterator itr = c.iterator();
|
|
||||||
int csize = c.size();
|
|
||||||
|
|
||||||
if (csize + size > data.length)
|
|
||||||
ensureCapacity(size + csize);
|
|
||||||
int end = index + csize;
|
|
||||||
if (size > 0 && index != size)
|
|
||||||
System.arraycopy(data, index, data, end, csize);
|
|
||||||
size += csize;
|
|
||||||
for (; index < end; index++)
|
|
||||||
{
|
|
||||||
data[index] = itr.next();
|
|
||||||
}
|
|
||||||
return (csize > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a shallow copy of this ArrayList
|
* Returns the highest index at which element appears in this List, or
|
||||||
|
* -1 if it does not appear.
|
||||||
|
*
|
||||||
|
* @param e the element whose inclusion in the List is being tested
|
||||||
|
* @return the index where e was found
|
||||||
|
*/
|
||||||
|
public int lastIndexOf(Object e)
|
||||||
|
{
|
||||||
|
for (int i = size - 1; i >= 0; i--)
|
||||||
|
if (equals(e, data[i]))
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shallow copy of this ArrayList (elements are not cloned).
|
||||||
|
*
|
||||||
|
* @return the cloned object
|
||||||
*/
|
*/
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
ArrayList clone = null;
|
ArrayList clone = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clone = (ArrayList) super.clone();
|
clone = (ArrayList) super.clone();
|
||||||
clone.data = new Object[data.length];
|
clone.data = (Object[]) data.clone();
|
||||||
System.arraycopy(data, 0, clone.data, 0, size);
|
}
|
||||||
|
catch (CloneNotSupportedException e)
|
||||||
|
{
|
||||||
|
// Impossible to get here.
|
||||||
}
|
}
|
||||||
catch (CloneNotSupportedException e) {}
|
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true iff oElement is in this ArrayList.
|
* Returns an Object array containing all of the elements in this ArrayList.
|
||||||
|
* The array is independent of this list.
|
||||||
*
|
*
|
||||||
* @param e the element whose inclusion in the List is being
|
* @return an array representation of this list
|
||||||
* tested
|
|
||||||
*/
|
|
||||||
public boolean contains(Object e)
|
|
||||||
{
|
|
||||||
return (indexOf(e) != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the lowest index at which oElement appears in this List, or
|
|
||||||
* -1 if it does not appear.
|
|
||||||
*
|
|
||||||
* @param e the element whose inclusion in the List is being
|
|
||||||
* tested
|
|
||||||
*/
|
|
||||||
public int indexOf(Object e)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
if (e == null ? data[i] == null : e.equals(data[i]))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the highest index at which oElement appears in this List, or
|
|
||||||
* -1 if it does not appear.
|
|
||||||
*
|
|
||||||
* @param e the element whose inclusion in the List is being
|
|
||||||
* tested
|
|
||||||
*/
|
|
||||||
public int lastIndexOf(Object e)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = size - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (e == null ? data[i] == null : e.equals(data[i]))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all elements from this List
|
|
||||||
*/
|
|
||||||
public void clear()
|
|
||||||
{
|
|
||||||
modCount++;
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
data[i] = null;
|
|
||||||
}
|
|
||||||
size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the element at the specified index.
|
|
||||||
*
|
|
||||||
* @param index the index at which the element is being set
|
|
||||||
* @param e the element to be set
|
|
||||||
* @return the element previously at the specified index, or null if
|
|
||||||
* none was there
|
|
||||||
*/
|
|
||||||
public Object set(int index, Object e)
|
|
||||||
{
|
|
||||||
Object result;
|
|
||||||
if (index < 0 || index >= size)
|
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" +
|
|
||||||
size);
|
|
||||||
result = data[index];
|
|
||||||
// SEH: no structural change, so don't update modCount
|
|
||||||
data[index] = e;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an Object Array containing all of the elements in this ArrayList
|
|
||||||
*/
|
*/
|
||||||
public Object[] toArray()
|
public Object[] toArray()
|
||||||
{
|
{
|
||||||
|
@ -356,62 +266,304 @@ public class ArrayList extends AbstractList
|
||||||
* Returns an Array whose component type is the runtime component type of
|
* Returns an Array whose component type is the runtime component type of
|
||||||
* the passed-in Array. The returned Array is populated with all of the
|
* the passed-in Array. The returned Array is populated with all of the
|
||||||
* elements in this ArrayList. If the passed-in Array is not large enough
|
* elements in this ArrayList. If the passed-in Array is not large enough
|
||||||
* to store all of the elements in this List, a new Array will be created
|
* to store all of the elements in this List, a new Array will be created
|
||||||
* and returned; if the passed-in Array is <i>larger</i> than the size
|
* and returned; if the passed-in Array is <i>larger</i> than the size
|
||||||
* of this List, then size() index will be set to null.
|
* of this List, then size() index will be set to null.
|
||||||
*
|
*
|
||||||
* @param array the passed-in Array
|
* @param a the passed-in Array
|
||||||
|
* @return an array representation of this list
|
||||||
|
* @throws ArrayStoreException if the runtime type of a does not allow
|
||||||
|
* an element in this list
|
||||||
|
* @throws NullPointerException if a is null
|
||||||
*/
|
*/
|
||||||
public Object[] toArray(Object[] array)
|
public Object[] toArray(Object[] a)
|
||||||
{
|
{
|
||||||
if (array.length < size)
|
if (a.length < size)
|
||||||
array = (Object[]) Array.newInstance(array.getClass().getComponentType(),
|
a = (Object[]) Array.newInstance(a.getClass().getComponentType(),
|
||||||
size);
|
size);
|
||||||
else if (array.length > size)
|
else if (a.length > size)
|
||||||
array[size] = null;
|
a[size] = null;
|
||||||
System.arraycopy(data, 0, array, 0, size);
|
System.arraycopy(data, 0, a, 0, size);
|
||||||
return array;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trims the capacity of this List to be equal to its size;
|
* Retrieves the element at the user-supplied index.
|
||||||
* a memory saver.
|
*
|
||||||
|
* @param index the index of the element we are fetching
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||||
*/
|
*/
|
||||||
public void trimToSize()
|
public Object get(int index)
|
||||||
{
|
{
|
||||||
// not a structural change from the perspective of iterators on this list,
|
checkBoundExclusive(index);
|
||||||
// so don't update modCount
|
return data[index];
|
||||||
Object[] newData = new Object[size];
|
|
||||||
System.arraycopy(data, 0, newData, 0, size);
|
|
||||||
data = newData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream out) throws IOException
|
/**
|
||||||
|
* Sets the element at the specified index.
|
||||||
|
*
|
||||||
|
* @param index the index at which the element is being set
|
||||||
|
* @param e the element to be set
|
||||||
|
* @return the element previously at the specified index
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= 0
|
||||||
|
*/
|
||||||
|
public Object set(int index, Object e)
|
||||||
|
{
|
||||||
|
checkBoundExclusive(index);
|
||||||
|
Object result = data[index];
|
||||||
|
data[index] = e;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the supplied element to the end of this list.
|
||||||
|
*
|
||||||
|
* @param e the element to be appended to this list
|
||||||
|
* @return true, the add will always succeed
|
||||||
|
*/
|
||||||
|
public boolean add(Object e)
|
||||||
|
{
|
||||||
|
modCount++;
|
||||||
|
if (size == data.length)
|
||||||
|
ensureCapacity(size + 1);
|
||||||
|
data[size++] = e;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the supplied element at the specified index, shifting all
|
||||||
|
* elements currently at that index or higher one to the right.
|
||||||
|
*
|
||||||
|
* @param index the index at which the element is being added
|
||||||
|
* @param e the item being added
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index > size()
|
||||||
|
*/
|
||||||
|
public void add(int index, Object e)
|
||||||
|
{
|
||||||
|
checkBoundInclusive(index);
|
||||||
|
modCount++;
|
||||||
|
if (size == data.length)
|
||||||
|
ensureCapacity(size + 1);
|
||||||
|
if (index != size)
|
||||||
|
System.arraycopy(data, index, data, index + 1, size - index);
|
||||||
|
data[index] = e;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the element at the user-supplied index.
|
||||||
|
*
|
||||||
|
* @param index the index of the element to be removed
|
||||||
|
* @return the removed Object
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size()
|
||||||
|
*/
|
||||||
|
public Object remove(int index)
|
||||||
|
{
|
||||||
|
checkBoundExclusive(index);
|
||||||
|
Object r = data[index];
|
||||||
|
modCount++;
|
||||||
|
if (index != --size)
|
||||||
|
System.arraycopy(data, index + 1, data, index, size - index);
|
||||||
|
// Aid for garbage collection by releasing this pointer.
|
||||||
|
data[size] = null;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all elements from this List
|
||||||
|
*/
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
modCount++;
|
||||||
|
// Allow for garbage collection.
|
||||||
|
Arrays.fill(data, 0, size, null);
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add each element in the supplied Collection to this List. It is undefined
|
||||||
|
* what happens if you modify the list while this is taking place; for
|
||||||
|
* example, if the collection contains this list.
|
||||||
|
*
|
||||||
|
* @param c a Collection containing elements to be added to this List
|
||||||
|
* @return true if the list was modified, in other words c is not empty
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
|
*/
|
||||||
|
public boolean addAll(Collection c)
|
||||||
|
{
|
||||||
|
return addAll(size, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all elements in the supplied collection, inserting them beginning
|
||||||
|
* at the specified index.
|
||||||
|
*
|
||||||
|
* @param index the index at which the elements will be inserted
|
||||||
|
* @param c the Collection containing the elements to be inserted
|
||||||
|
* @throws IndexOutOfBoundsException if index < 0 || index > 0
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
|
*/
|
||||||
|
public boolean addAll(int index, Collection c)
|
||||||
|
{
|
||||||
|
checkBoundInclusive(index);
|
||||||
|
Iterator itr = c.iterator();
|
||||||
|
int csize = c.size();
|
||||||
|
|
||||||
|
modCount++;
|
||||||
|
if (csize + size > data.length)
|
||||||
|
ensureCapacity(size + csize);
|
||||||
|
int end = index + csize;
|
||||||
|
if (index != size)
|
||||||
|
System.arraycopy(data, index, data, end, csize);
|
||||||
|
size += csize;
|
||||||
|
for ( ; index < end; index++)
|
||||||
|
data[index] = itr.next();
|
||||||
|
return csize > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all elements in the half-open interval [fromIndex, toIndex).
|
||||||
|
* You asked for it if you call this with invalid arguments.
|
||||||
|
*
|
||||||
|
* @param fromIndex the first index which will be removed
|
||||||
|
* @param toIndex one greater than the last index which will be removed
|
||||||
|
*/
|
||||||
|
protected void removeRange(int fromIndex, int toIndex)
|
||||||
|
{
|
||||||
|
if (fromIndex != toIndex)
|
||||||
|
{
|
||||||
|
modCount++;
|
||||||
|
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex);
|
||||||
|
size -= toIndex - fromIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the index is in the range of possible elements (inclusive).
|
||||||
|
*
|
||||||
|
* @param index the index to check
|
||||||
|
* @throws IndexOutOfBoundsException if index > size
|
||||||
|
*/
|
||||||
|
private void checkBoundInclusive(int index)
|
||||||
|
{
|
||||||
|
// Implementation note: we do not check for negative ranges here, since
|
||||||
|
// use of a negative index will cause an ArrayIndexOutOfBoundsException,
|
||||||
|
// a subclass of the required exception, with no effort on our part.
|
||||||
|
if (index > size)
|
||||||
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
|
||||||
|
+ size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks that the index is in the range of existing elements (exclusive).
|
||||||
|
*
|
||||||
|
* @param index the index to check
|
||||||
|
* @throws IndexOutOfBoundsException if index >= size
|
||||||
|
*/
|
||||||
|
private void checkBoundExclusive(int index)
|
||||||
|
{
|
||||||
|
// Implementation note: we do not check for negative ranges here, since
|
||||||
|
// use of a negative index will cause an ArrayIndexOutOfBoundsException,
|
||||||
|
// a subclass of the required exception, with no effort on our part.
|
||||||
|
if (index >= size)
|
||||||
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
|
||||||
|
+ size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove from this list all elements contained in the given collection.
|
||||||
|
* This is not public, due to Sun's API, but this performs in linear
|
||||||
|
* time while the default behavior of AbstractList would be quadratic.
|
||||||
|
*
|
||||||
|
* @param c the collection to filter out
|
||||||
|
* @return true if this list changed
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
|
*/
|
||||||
|
boolean removeAllInternal(Collection c)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int j;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
if (c.contains(data[i]))
|
||||||
|
break;
|
||||||
|
if (i == size)
|
||||||
|
return false;
|
||||||
|
|
||||||
// The 'size' field.
|
modCount++;
|
||||||
out.defaultWriteObject();
|
for (j = i++; i < size; i++)
|
||||||
|
if (! c.contains(data[i]))
|
||||||
// FIXME: Do we really want to serialize unused list entries??
|
data[j++] = data[i];
|
||||||
out.writeInt(data.length);
|
size -= i - j;
|
||||||
for (i = 0; i < data.length; i++)
|
return true;
|
||||||
out.writeObject(data[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readObject(ObjectInputStream in)
|
/**
|
||||||
|
* Retain in this vector only the elements contained in the given collection.
|
||||||
|
* This is not public, due to Sun's API, but this performs in linear
|
||||||
|
* time while the default behavior of AbstractList would be quadratic.
|
||||||
|
*
|
||||||
|
* @param c the collection to filter by
|
||||||
|
* @return true if this vector changed
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
boolean retainAllInternal(Collection c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
if (! c.contains(data[i]))
|
||||||
|
break;
|
||||||
|
if (i == size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
modCount++;
|
||||||
|
for (j = i++; i < size; i++)
|
||||||
|
if (c.contains(data[i]))
|
||||||
|
data[j++] = data[i];
|
||||||
|
size -= i - j;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes this object to the given stream.
|
||||||
|
*
|
||||||
|
* @param out the stream to write to
|
||||||
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the size field (int), the length of the backing array
|
||||||
|
* (int), followed by its elements (Objects) in proper order.
|
||||||
|
*/
|
||||||
|
private void writeObject(ObjectOutputStream s) throws IOException
|
||||||
|
{
|
||||||
|
// The 'size' field.
|
||||||
|
s.defaultWriteObject();
|
||||||
|
// We serialize unused list entries to preserve capacity.
|
||||||
|
int len = data.length;
|
||||||
|
s.writeInt(len);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
s.writeObject(data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserializes this object from the given stream.
|
||||||
|
*
|
||||||
|
* @param in the stream to read from
|
||||||
|
* @throws ClassNotFoundException if the underlying stream fails
|
||||||
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the size field (int), the length of the backing array
|
||||||
|
* (int), followed by its elements (Objects) in proper order.
|
||||||
|
*/
|
||||||
|
private void readObject(ObjectInputStream s)
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
int capacity;
|
|
||||||
|
|
||||||
// the `size' field.
|
// the `size' field.
|
||||||
in.defaultReadObject();
|
s.defaultReadObject();
|
||||||
|
int capacity = s.readInt();
|
||||||
capacity = in.readInt();
|
|
||||||
data = new Object[capacity];
|
data = new Object[capacity];
|
||||||
|
for (int i = 0; i < capacity; i++)
|
||||||
for (i = 0; i < capacity; i++)
|
data[i] = s.readObject();
|
||||||
data[i] = in.readObject();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/* BasicMapEntry.java -- a class providing a plain-vanilla implementation of
|
/* BasicMapEntry.java -- a class providing a plain-vanilla implementation of
|
||||||
the Map.Entry interface; could be used anywhere in java.util
|
the Map.Entry interface; could be used anywhere in java.util
|
||||||
Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -29,52 +29,113 @@ executable file might be covered by the GNU General Public License. */
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which implements Map.Entry. It is shared by HashMap, TreeMap, and
|
* A class which implements Map.Entry. It is shared by HashMap, TreeMap,
|
||||||
* Hashtable.
|
* Hashtable, and Collections. It is not specified by the JDK, but makes
|
||||||
|
* life much easier.
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
*/
|
*/
|
||||||
class BasicMapEntry implements Map.Entry
|
class BasicMapEntry implements Map.Entry
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The key. Package visible for direct manipulation.
|
||||||
|
*/
|
||||||
Object key;
|
Object key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value. Package visible for direct manipulation.
|
||||||
|
*/
|
||||||
Object value;
|
Object value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic constructor initializes the fields.
|
||||||
|
* @param newKey the key
|
||||||
|
* @param newValue the value
|
||||||
|
*/
|
||||||
BasicMapEntry(Object newKey, Object newValue)
|
BasicMapEntry(Object newKey, Object newValue)
|
||||||
{
|
{
|
||||||
key = newKey;
|
key = newKey;
|
||||||
value = newValue;
|
value = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the specified object with this entry. Returns true only if
|
||||||
|
* the object is a mapping of identical key and value. In other words,
|
||||||
|
* this must be:
|
||||||
|
* <pre>
|
||||||
|
* (o instanceof Map.Entry) &&
|
||||||
|
* (getKey() == null ? ((HashMap) o).getKey() == null
|
||||||
|
* : getKey().equals(((HashMap) o).getKey())) &&
|
||||||
|
* (getValue() == null ? ((HashMap) o).getValue() == null
|
||||||
|
* : getValue().equals(((HashMap) o).getValue()))
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param o the object to compare
|
||||||
|
* @return true if it is equal
|
||||||
|
*/
|
||||||
public final boolean equals(Object o)
|
public final boolean equals(Object o)
|
||||||
{
|
{
|
||||||
if (!(o instanceof Map.Entry))
|
if (! (o instanceof Map.Entry))
|
||||||
return false;
|
return false;
|
||||||
|
// Optimize for our own entries.
|
||||||
|
if (o instanceof BasicMapEntry)
|
||||||
|
{
|
||||||
|
BasicMapEntry e = (BasicMapEntry) o;
|
||||||
|
return (AbstractCollection.equals(key, e.key)
|
||||||
|
&& AbstractCollection.equals(value, e.value));
|
||||||
|
}
|
||||||
Map.Entry e = (Map.Entry) o;
|
Map.Entry e = (Map.Entry) o;
|
||||||
return (key == null ? e.getKey() == null : key.equals(e.getKey())
|
return (AbstractCollection.equals(key, e.getKey())
|
||||||
&& value == null ? e.getValue() == null
|
&& AbstractCollection.equals(value, e.getValue()));
|
||||||
: value.equals(e.getValue()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the key corresponding to this entry.
|
||||||
|
*
|
||||||
|
* @return the key
|
||||||
|
*/
|
||||||
public final Object getKey()
|
public final Object getKey()
|
||||||
{
|
{
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value corresponding to this entry. If you already called
|
||||||
|
* Iterator.remove(), the behavior undefined, but in this case it works.
|
||||||
|
*
|
||||||
|
* @return the value
|
||||||
|
*/
|
||||||
public final Object getValue()
|
public final Object getValue()
|
||||||
{
|
{
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the hash code of the entry. This is defined as the exclusive-or
|
||||||
|
* of the hashcodes of the key and value (using 0 for null). In other
|
||||||
|
* words, this must be:
|
||||||
|
* <pre>
|
||||||
|
* (getKey() == null ? 0 : getKey().hashCode()) ^
|
||||||
|
* (getValue() == null ? 0 : getValue().hashCode())
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return the hash code
|
||||||
|
*/
|
||||||
public final int hashCode()
|
public final int hashCode()
|
||||||
{
|
{
|
||||||
int kc = (key == null ? 0 : key.hashCode());
|
return (AbstractCollection.hashCode(key)
|
||||||
int vc = (value == null ? 0 : value.hashCode());
|
^ AbstractCollection.hashCode(value));
|
||||||
return kc ^ vc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sets the value of this Map.Entry. Note that this is overriden by
|
* Replaces the value with the specified object. This writes through
|
||||||
* Hashtable.Entry, which does not permit a null value.
|
* to the map, unless you have already called Iterator.remove(). It
|
||||||
|
* may be overridden to restrict a null value.
|
||||||
|
*
|
||||||
|
* @param newVal the new value to store
|
||||||
|
* @return the old value
|
||||||
|
* @throws NullPointerException if the map forbids null values
|
||||||
*/
|
*/
|
||||||
public Object setValue(Object newVal)
|
public Object setValue(Object newVal)
|
||||||
{
|
{
|
||||||
|
@ -83,6 +144,12 @@ class BasicMapEntry implements Map.Entry
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This provides a string representation of the entry. It is of the form
|
||||||
|
* "key=value", where string concatenation is used on key and value.
|
||||||
|
*
|
||||||
|
* @return the string representation
|
||||||
|
*/
|
||||||
public final String toString()
|
public final String toString()
|
||||||
{
|
{
|
||||||
return key + "=" + value;
|
return key + "=" + value;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// BitSet - A vector of bits.
|
/* BitSet.java -- A vector of bits.
|
||||||
|
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
|
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -50,22 +49,32 @@ import java.io.Serializable;
|
||||||
* while another thread is simultaneously modifying it, the results are
|
* while another thread is simultaneously modifying it, the results are
|
||||||
* undefined.
|
* undefined.
|
||||||
*
|
*
|
||||||
* @specnote Historically, there has been some confusion as to whether or not
|
|
||||||
* this class should be synchronized. From an efficiency perspective,
|
|
||||||
* it is very undesirable to synchronize it because multiple locks
|
|
||||||
* and explicit lock ordering are required to safely synchronize some
|
|
||||||
* methods. The JCL 1.2 supplement book specifies that as of JDK
|
|
||||||
* 1.2, the class is no longer synchronized.
|
|
||||||
*
|
|
||||||
* @author Jochen Hoenicke
|
* @author Jochen Hoenicke
|
||||||
* @author Tom Tromey <tromey@cygnus.com>
|
* @author Tom Tromey <tromey@cygnus.com>
|
||||||
* @date October 23, 1998.
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
* @status API complete to JDK 1.3.
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class BitSet implements Cloneable, Serializable
|
public class BitSet implements Cloneable, Serializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Create a new empty bit set.
|
* Compatible with JDK 1.0.
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 7997698588986878753L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common mask.
|
||||||
|
*/
|
||||||
|
private static final int LONG_MASK = 0x3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The actual bits.
|
||||||
|
* @serial the i'th bit is in bits[i/64] at position i%64 (where position
|
||||||
|
* 0 is the least significant).
|
||||||
|
*/
|
||||||
|
private long[] bits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new empty bit set. All bits are initially false.
|
||||||
*/
|
*/
|
||||||
public BitSet()
|
public BitSet()
|
||||||
{
|
{
|
||||||
|
@ -75,18 +84,15 @@ public class BitSet implements Cloneable, Serializable
|
||||||
/**
|
/**
|
||||||
* Create a new empty bit set, with a given size. This
|
* Create a new empty bit set, with a given size. This
|
||||||
* constructor reserves enough space to represent the integers
|
* constructor reserves enough space to represent the integers
|
||||||
* from <code>0</code> to <code>nbits-1</code>.
|
* from <code>0</code> to <code>nbits-1</code>.
|
||||||
* @param nbits the initial size of the bit set.
|
*
|
||||||
* @throws NegativeArraySizeException if the specified initial
|
* @param nbits the initial size of the bit set
|
||||||
* size is negative.
|
* @throws NegativeArraySizeException if nbits < 0
|
||||||
* @require nbits >= 0
|
|
||||||
*/
|
*/
|
||||||
public BitSet(int nbits)
|
public BitSet(int nbits)
|
||||||
{
|
{
|
||||||
if (nbits < 0)
|
int length = nbits >>> 6;
|
||||||
throw new NegativeArraySizeException();
|
if ((nbits & LONG_MASK) != 0)
|
||||||
int length = nbits / 64;
|
|
||||||
if (nbits % 64 != 0)
|
|
||||||
++length;
|
++length;
|
||||||
bits = new long[length];
|
bits = new long[length];
|
||||||
}
|
}
|
||||||
|
@ -95,8 +101,9 @@ public class BitSet implements Cloneable, Serializable
|
||||||
* Performs the logical AND operation on this bit set and the
|
* Performs the logical AND operation on this bit set and the
|
||||||
* given <code>set</code>. This means it builds the intersection
|
* given <code>set</code>. This means it builds the intersection
|
||||||
* of the two sets. The result is stored into this bit set.
|
* of the two sets. The result is stored into this bit set.
|
||||||
* @param set the second bit set.
|
*
|
||||||
* @require set != null
|
* @param set the second bit set
|
||||||
|
* @throws NullPointerException if set is null
|
||||||
*/
|
*/
|
||||||
public void and(BitSet bs)
|
public void and(BitSet bs)
|
||||||
{
|
{
|
||||||
|
@ -104,63 +111,143 @@ public class BitSet implements Cloneable, Serializable
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < max; ++i)
|
for (i = 0; i < max; ++i)
|
||||||
bits[i] &= bs.bits[i];
|
bits[i] &= bs.bits[i];
|
||||||
for (; i < bits.length; ++i)
|
while (i < bits.length)
|
||||||
bits[i] = 0;
|
bits[i++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the logical AND operation on this bit set and the
|
* Performs the logical AND operation on this bit set and the
|
||||||
* complement of the given <code>set</code>. This means it
|
* complement of the given <code>set</code>. This means it
|
||||||
* selects every element in the first set, that isn't in the
|
* selects every element in the first set, that isn't in the
|
||||||
* second set. The result is stored into this bit set.
|
* second set. The result is stored into this bit set.
|
||||||
* @param set the second bit set.
|
*
|
||||||
* @require set != null
|
* @param set the second bit set
|
||||||
* @since JDK1.2
|
* @throws NullPointerException if set is null
|
||||||
|
* @since 1.2
|
||||||
*/
|
*/
|
||||||
public void andNot(BitSet bs)
|
public void andNot(BitSet bs)
|
||||||
{
|
{
|
||||||
int max = Math.min(bits.length, bs.bits.length);
|
int i = Math.min(bits.length, bs.bits.length);
|
||||||
int i;
|
while (--i >= 0)
|
||||||
for (i = 0; i < max; ++i)
|
|
||||||
bits[i] &= ~bs.bits[i];
|
bits[i] &= ~bs.bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bits set to true.
|
||||||
|
*
|
||||||
|
* @return the number of true bits
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public int cardinality()
|
||||||
|
{
|
||||||
|
int card = 0;
|
||||||
|
for (int i = bits.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
long a = bits[i];
|
||||||
|
// Take care of common cases.
|
||||||
|
if (a == 0)
|
||||||
|
continue;
|
||||||
|
if (a == -1)
|
||||||
|
{
|
||||||
|
card += 64;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successively collapse alternating bit groups into a sum.
|
||||||
|
a = ((a >> 1) & 0x5555555555555555L) + (a & 0x5555555555555555L);
|
||||||
|
a = ((a >> 2) & 0x3333333333333333L) + (a & 0x3333333333333333L);
|
||||||
|
int b = (int) ((a >>> 32) + a);
|
||||||
|
b = ((b >> 4) & 0x0f0f0f0f) + (b & 0x0f0f0f0f);
|
||||||
|
b = ((b >> 8) & 0x00ff00ff) + (b & 0x00ff00ff);
|
||||||
|
card += ((b >> 16) & 0x0000ffff) + (b & 0x0000ffff);
|
||||||
|
}
|
||||||
|
return card;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all bits in the set to false.
|
||||||
|
*
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
Arrays.fill(bits, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the integer <code>bitIndex</code> from this set. That is
|
* Removes the integer <code>bitIndex</code> from this set. That is
|
||||||
* the corresponding bit is cleared. If the index is not in the set,
|
* the corresponding bit is cleared. If the index is not in the set,
|
||||||
* this method does nothing.
|
* this method does nothing.
|
||||||
* @param bitIndex a non-negative integer.
|
*
|
||||||
* @exception ArrayIndexOutOfBoundsException if the specified bit index
|
* @param bitIndex a non-negative integer
|
||||||
* is negative.
|
* @throws IndexOutOfBoundsException if bitIndex < 0
|
||||||
* @require bitIndex >= 0
|
|
||||||
*/
|
*/
|
||||||
public void clear(int pos)
|
public void clear(int pos)
|
||||||
{
|
{
|
||||||
if (pos < 0)
|
int offset = pos >>> 6;
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
int bit = pos % 64;
|
|
||||||
int offset = pos / 64;
|
|
||||||
ensure(offset);
|
ensure(offset);
|
||||||
bits[offset] &= ~(1L << bit);
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
|
// so we'll just let that be our exception.
|
||||||
|
bits[offset] &= ~(1L << pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bits between from (inclusive) and to (exclusive) to false.
|
||||||
|
*
|
||||||
|
* @param from the start range (inclusive)
|
||||||
|
* @param to the end range (exclusive)
|
||||||
|
* @throws IndexOutOfBoundsException if from < 0 || from > to
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void clear(int from, int to)
|
||||||
|
{
|
||||||
|
if (from < 0 || from > to)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
if (from == to)
|
||||||
|
return;
|
||||||
|
int lo_offset = from >>> 6;
|
||||||
|
int hi_offset = to >>> 6;
|
||||||
|
ensure(hi_offset);
|
||||||
|
if (lo_offset == hi_offset)
|
||||||
|
{
|
||||||
|
bits[hi_offset] &= ((1L << from) - 1) | (-1L << to);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits[lo_offset] &= (1L << from) - 1;
|
||||||
|
bits[hi_offset] &= -1L << to;
|
||||||
|
for (int i = lo_offset + 1; i < hi_offset; i++)
|
||||||
|
bits[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a clone of this bit set, that is an instance of the same
|
* Create a clone of this bit set, that is an instance of the same
|
||||||
* class and contains the same elements. But it doesn't change when
|
* class and contains the same elements. But it doesn't change when
|
||||||
* this bit set changes.
|
* this bit set changes.
|
||||||
|
*
|
||||||
* @return the clone of this object.
|
* @return the clone of this object.
|
||||||
*/
|
*/
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
BitSet bs = new BitSet(bits.length * 64);
|
try
|
||||||
System.arraycopy(bits, 0, bs.bits, 0, bits.length);
|
{
|
||||||
return bs;
|
BitSet bs = (BitSet) super.clone();
|
||||||
|
bs.bits = (long[]) bits.clone();
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
catch (CloneNotSupportedException e)
|
||||||
|
{
|
||||||
|
// Impossible to get here.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the <code>obj</code> is a bit set that contains
|
* Returns true if the <code>obj</code> is a bit set that contains
|
||||||
* exactly the same elements as this bit set, otherwise false.
|
* exactly the same elements as this bit set, otherwise false.
|
||||||
* @return true if obj equals this bit set.
|
*
|
||||||
|
* @param obj the object to compare to
|
||||||
|
* @return true if obj equals this bit set
|
||||||
*/
|
*/
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
|
@ -171,42 +258,124 @@ public class BitSet implements Cloneable, Serializable
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < max; ++i)
|
for (i = 0; i < max; ++i)
|
||||||
if (bits[i] != bs.bits[i])
|
if (bits[i] != bs.bits[i])
|
||||||
return false;
|
return false;
|
||||||
// If one is larger, check to make sure all extra bits are 0.
|
// If one is larger, check to make sure all extra bits are 0.
|
||||||
for (int j = i; j < bits.length; ++j)
|
for (int j = i; j < bits.length; ++j)
|
||||||
if (bits[j] != 0)
|
if (bits[j] != 0)
|
||||||
return false;
|
return false;
|
||||||
for (int j = i; j < bs.bits.length; ++j)
|
for (int j = i; j < bs.bits.length; ++j)
|
||||||
if (bs.bits[j] != 0)
|
if (bs.bits[j] != 0)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit at the index to the opposite value.
|
||||||
|
*
|
||||||
|
* @param index the index of the bit
|
||||||
|
* @throws IndexOutOfBoundsException if index is negative
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void flip(int index)
|
||||||
|
{
|
||||||
|
int offset = index >>> 6;
|
||||||
|
ensure(offset);
|
||||||
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
|
// so we'll just let that be our exception.
|
||||||
|
bits[offset] ^= 1L << index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a range of bits to the opposite value.
|
||||||
|
*
|
||||||
|
* @param from the low index (inclusive)
|
||||||
|
* @param to the high index (exclusive)
|
||||||
|
* @throws IndexOutOfBoundsException if from > to || from < 0
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void flip(int from, int to)
|
||||||
|
{
|
||||||
|
if (from < 0 || from > to)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
if (from == to)
|
||||||
|
return;
|
||||||
|
int lo_offset = from >>> 6;
|
||||||
|
int hi_offset = to >>> 6;
|
||||||
|
ensure(hi_offset);
|
||||||
|
if (lo_offset == hi_offset)
|
||||||
|
{
|
||||||
|
bits[hi_offset] ^= (-1L << from) & ((1L << to) - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits[lo_offset] ^= -1L << from;
|
||||||
|
bits[hi_offset] ^= (1L << to) - 1;
|
||||||
|
for (int i = lo_offset + 1; i < hi_offset; i++)
|
||||||
|
bits[i] ^= -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the integer <code>bitIndex</code> is in this bit
|
* Returns true if the integer <code>bitIndex</code> is in this bit
|
||||||
* set, otherwise false.
|
* set, otherwise false.
|
||||||
* @param bitIndex a non-negative integer
|
*
|
||||||
* @return the value of the bit at the specified index.
|
* @param pos a non-negative integer
|
||||||
* @exception ArrayIndexOutOfBoundsException if the specified bit index
|
* @return the value of the bit at the specified index
|
||||||
* is negative.
|
* @throws IndexOutOfBoundsException if the index is negative
|
||||||
* @require bitIndex >= 0
|
|
||||||
*/
|
*/
|
||||||
public boolean get(int pos)
|
public boolean get(int pos)
|
||||||
{
|
{
|
||||||
if (pos < 0)
|
int offset = pos >>> 6;
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
|
|
||||||
int bit = pos % 64;
|
|
||||||
int offset = pos / 64;
|
|
||||||
|
|
||||||
if (offset >= bits.length)
|
if (offset >= bits.length)
|
||||||
return false;
|
return false;
|
||||||
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
return (bits[offset] & (1L << bit)) == 0 ? false : true;
|
// so we'll just let that be our exception.
|
||||||
|
return (bits[offset] & (1L << pos)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a hash code value for this bit set. The hash code of
|
* Returns a new <code>BitSet</code> composed of a range of bits from
|
||||||
|
* this one.
|
||||||
|
*
|
||||||
|
* @param from the low index (inclusive)
|
||||||
|
* @param to the high index (exclusive)
|
||||||
|
* @throws IndexOutOfBoundsException if from > to || from < 0
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public BitSet get(int from, int to)
|
||||||
|
{
|
||||||
|
if (from < 0 || from > to)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
BitSet bs = new BitSet(to - from);
|
||||||
|
int lo_offset = from >>> 6;
|
||||||
|
if (lo_offset >= bits.length)
|
||||||
|
return bs;
|
||||||
|
|
||||||
|
int lo_bit = from & LONG_MASK;
|
||||||
|
int hi_offset = to >>> 6;
|
||||||
|
if (lo_bit == 0)
|
||||||
|
{
|
||||||
|
int len = Math.min(hi_offset - lo_offset + 1, bits.length - lo_offset);
|
||||||
|
System.arraycopy(bits, lo_offset, bs.bits, 0, len);
|
||||||
|
if (hi_offset < bits.length)
|
||||||
|
bs.bits[hi_offset - lo_offset] &= (1L << to) - 1;
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = Math.min(hi_offset, bits.length - 1);
|
||||||
|
int reverse = ~lo_bit;
|
||||||
|
int i;
|
||||||
|
for (i = 0; lo_offset < len; lo_offset++, i++)
|
||||||
|
bs.bits[i] = ((bits[lo_offset] >>> lo_bit)
|
||||||
|
| (bits[lo_offset + 1] << reverse));
|
||||||
|
if ((to & LONG_MASK) > lo_bit)
|
||||||
|
bs.bits[i++] = bits[lo_offset] >>> lo_bit;
|
||||||
|
if (hi_offset < bits.length)
|
||||||
|
bs.bits[i - 1] &= (1L << (to - from)) - 1;
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a hash code value for this bit set. The hash code of
|
||||||
* two bit sets containing the same integers is identical. The algorithm
|
* two bit sets containing the same integers is identical. The algorithm
|
||||||
* used to compute it is as follows:
|
* used to compute it is as follows:
|
||||||
*
|
*
|
||||||
|
@ -233,21 +402,55 @@ public class BitSet implements Cloneable, Serializable
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* Note that the hash code values changes, if the set is changed.
|
* Note that the hash code values changes, if the set is changed.
|
||||||
|
*
|
||||||
* @return the hash code value for this bit set.
|
* @return the hash code value for this bit set.
|
||||||
*/
|
*/
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
long h = 1234;
|
long h = 1234;
|
||||||
for (int i = bits.length - 1; i >= 0; --i)
|
for (int i = bits.length; i > 0; )
|
||||||
h ^= bits[i] * (i + 1);
|
h ^= i * bits[--i];
|
||||||
return (int) ((h >> 32) ^ h);
|
return (int) ((h >> 32) ^ h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the specified BitSet and this one share at least one
|
||||||
|
* common true bit.
|
||||||
|
*
|
||||||
|
* @param set the set to check for intersection
|
||||||
|
* @return true if the sets intersect
|
||||||
|
* @throws NullPointerException if set is null
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public boolean intersects(BitSet set)
|
||||||
|
{
|
||||||
|
int i = Math.min(bits.length, set.bits.length);
|
||||||
|
while (--i >= 0)
|
||||||
|
if ((bits[i] & set.bits[i]) != 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this set contains no true bits.
|
||||||
|
*
|
||||||
|
* @return true if all bits are false
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
for (int i = bits.length - 1; i >= 0; i--)
|
||||||
|
if (bits[i] != 0)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the logical number of bits actually used by this bit
|
* Returns the logical number of bits actually used by this bit
|
||||||
* set. It returns the index of the highest set bit plus one.
|
* set. It returns the index of the highest set bit plus one.
|
||||||
* Note that this method doesn't return the number of set bits.
|
* Note that this method doesn't return the number of set bits.
|
||||||
* @return the index of the highest set bit plus one.
|
*
|
||||||
|
* @return the index of the highest set bit plus one.
|
||||||
*/
|
*/
|
||||||
public int length()
|
public int length()
|
||||||
{
|
{
|
||||||
|
@ -266,54 +469,186 @@ public class BitSet implements Cloneable, Serializable
|
||||||
// b >= 0 checks if the highest bit is zero.
|
// b >= 0 checks if the highest bit is zero.
|
||||||
while (b >= 0)
|
while (b >= 0)
|
||||||
{
|
{
|
||||||
--len;
|
--len;
|
||||||
b <<= 1;
|
b <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the next false bit, from the specified bit
|
||||||
|
* (inclusive).
|
||||||
|
*
|
||||||
|
* @param from the start location
|
||||||
|
* @return the first false bit
|
||||||
|
* @throws IndexOutOfBoundsException if from is negative
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public int nextClearBit(int from)
|
||||||
|
{
|
||||||
|
int offset = from >>> 6;
|
||||||
|
long mask = 1L << from;
|
||||||
|
while (offset < bits.length)
|
||||||
|
{
|
||||||
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
|
// so we'll just let that be our exception.
|
||||||
|
long h = bits[offset];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((h & mask) == 0)
|
||||||
|
return from;
|
||||||
|
mask <<= 1;
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
while (mask != 0);
|
||||||
|
mask = 1;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the next true bit, from the specified bit
|
||||||
|
* (inclusive). If there is none, -1 is returned. You can iterate over
|
||||||
|
* all true bits with this loop:<br>
|
||||||
|
* <pre>
|
||||||
|
* for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1))
|
||||||
|
* { // operate on i here }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param from the start location
|
||||||
|
* @return the first true bit, or -1
|
||||||
|
* @throws IndexOutOfBoundsException if from is negative
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public int nextSetBit(int from)
|
||||||
|
{
|
||||||
|
int offset = from >>> 6;
|
||||||
|
long mask = 1L << from;
|
||||||
|
while (offset < bits.length)
|
||||||
|
{
|
||||||
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
|
// so we'll just let that be our exception.
|
||||||
|
long h = bits[offset];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ((h & mask) != 0)
|
||||||
|
return from;
|
||||||
|
mask <<= 1;
|
||||||
|
from++;
|
||||||
|
}
|
||||||
|
while (mask != 0);
|
||||||
|
mask = 1;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the logical OR operation on this bit set and the
|
* Performs the logical OR operation on this bit set and the
|
||||||
* given <code>set</code>. This means it builds the union
|
* given <code>set</code>. This means it builds the union
|
||||||
* of the two sets. The result is stored into this bit set, which
|
* of the two sets. The result is stored into this bit set, which
|
||||||
* grows as necessary.
|
* grows as necessary.
|
||||||
* @param set the second bit set.
|
*
|
||||||
* @exception OutOfMemoryError if the current set can't grow.
|
* @param bs the second bit set
|
||||||
* @require set != null
|
* @throws NullPointerException if bs is null
|
||||||
*/
|
*/
|
||||||
public void or(BitSet bs)
|
public void or(BitSet bs)
|
||||||
{
|
{
|
||||||
ensure(bs.bits.length - 1);
|
ensure(bs.bits.length - 1);
|
||||||
int i;
|
for (int i = bs.bits.length - 1; i >= 0; i--)
|
||||||
for (i = 0; i < bs.bits.length; ++i)
|
|
||||||
bits[i] |= bs.bits[i];
|
bits[i] |= bs.bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the integer <code>bitIndex</code> to this set. That is
|
* Add the integer <code>bitIndex</code> to this set. That is
|
||||||
* the corresponding bit is set to true. If the index was already in
|
* the corresponding bit is set to true. If the index was already in
|
||||||
* the set, this method does nothing. The size of this structure
|
* the set, this method does nothing. The size of this structure
|
||||||
* is automatically increased as necessary.
|
* is automatically increased as necessary.
|
||||||
* @param bitIndex a non-negative integer.
|
*
|
||||||
* @exception ArrayIndexOutOfBoundsException if the specified bit index
|
* @param pos a non-negative integer.
|
||||||
* is negative.
|
* @throws IndexOutOfBoundsException if pos is negative
|
||||||
* @require bitIndex >= 0
|
|
||||||
*/
|
*/
|
||||||
public void set(int pos)
|
public void set(int pos)
|
||||||
{
|
{
|
||||||
if (pos < 0)
|
int offset = pos >>> 6;
|
||||||
throw new IndexOutOfBoundsException();
|
|
||||||
int bit = pos % 64;
|
|
||||||
int offset = pos / 64;
|
|
||||||
ensure(offset);
|
ensure(offset);
|
||||||
bits[offset] |= 1L << bit;
|
// ArrayIndexOutOfBoundsException subclasses IndexOutOfBoundsException,
|
||||||
|
// so we'll just let that be our exception.
|
||||||
|
bits[offset] |= 1L << pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bit at the given index to the specified value. The size of
|
||||||
|
* this structure is automatically increased as necessary.
|
||||||
|
*
|
||||||
|
* @param index the position to set
|
||||||
|
* @param value the value to set it to
|
||||||
|
* @throws IndexOutOfBoundsException if index is negative
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void set(int index, boolean value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
set(index);
|
||||||
|
else
|
||||||
|
clear(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bits between from (inclusive) and to (exclusive) to true.
|
||||||
|
*
|
||||||
|
* @param from the start range (inclusive)
|
||||||
|
* @param to the end range (exclusive)
|
||||||
|
* @throws IndexOutOfBoundsException if from < 0 || from > to
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void set(int from, int to)
|
||||||
|
{
|
||||||
|
if (from < 0 || from > to)
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
if (from == to)
|
||||||
|
return;
|
||||||
|
int lo_offset = from >>> 6;
|
||||||
|
int hi_offset = to >>> 6;
|
||||||
|
ensure(hi_offset);
|
||||||
|
if (lo_offset == hi_offset)
|
||||||
|
{
|
||||||
|
bits[hi_offset] |= (-1L << from) & ((1L << to) - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits[lo_offset] |= -1L << from;
|
||||||
|
bits[hi_offset] |= (1L << to) - 1;
|
||||||
|
for (int i = lo_offset + 1; i < hi_offset; i++)
|
||||||
|
bits[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the bits between from (inclusive) and to (exclusive) to the
|
||||||
|
* specified value.
|
||||||
|
*
|
||||||
|
* @param from the start range (inclusive)
|
||||||
|
* @param to the end range (exclusive)
|
||||||
|
* @param value the value to set it to
|
||||||
|
* @throws IndexOutOfBoundsException if from < 0 || from > to
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public void set(int from, int to, boolean value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
set(from, to);
|
||||||
|
else
|
||||||
|
clear(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of bits actually used by this bit set. Note
|
* Returns the number of bits actually used by this bit set. Note
|
||||||
* that this method doesn't return the number of set bits.
|
* that this method doesn't return the number of set bits, and that
|
||||||
* @returns the number of bits currently used.
|
* future requests for larger bits will make this automatically grow.
|
||||||
|
*
|
||||||
|
* @return the number of bits currently used.
|
||||||
*/
|
*/
|
||||||
public int size()
|
public int size()
|
||||||
{
|
{
|
||||||
|
@ -324,32 +659,32 @@ public class BitSet implements Cloneable, Serializable
|
||||||
* Returns the string representation of this bit set. This
|
* Returns the string representation of this bit set. This
|
||||||
* consists of a comma separated list of the integers in this set
|
* consists of a comma separated list of the integers in this set
|
||||||
* surrounded by curly braces. There is a space after each comma.
|
* surrounded by curly braces. There is a space after each comma.
|
||||||
|
* A sample string is thus "{1, 3, 53}".
|
||||||
* @return the string representation.
|
* @return the string representation.
|
||||||
*/
|
*/
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
String r = "{";
|
StringBuffer r = new StringBuffer("{");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (int i = 0; i < bits.length; ++i)
|
for (int i = 0; i < bits.length; ++i)
|
||||||
{
|
{
|
||||||
long bit = 1;
|
long bit = 1;
|
||||||
long word = bits[i];
|
long word = bits[i];
|
||||||
if (word == 0)
|
if (word == 0)
|
||||||
continue;
|
continue;
|
||||||
for (int j = 0; j < 64; ++j)
|
for (int j = 0; j < 64; ++j)
|
||||||
{
|
{
|
||||||
if ((word & bit) != 0)
|
if ((word & bit) != 0)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (! first)
|
||||||
r += ", ";
|
r.append(", ");
|
||||||
r += Integer.toString(64 * i + j);
|
r.append(64 * i + j);
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
bit <<= 1;
|
bit <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return r.append("}").toString();
|
||||||
return r += "}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -357,32 +692,30 @@ public class BitSet implements Cloneable, Serializable
|
||||||
* given <code>set</code>. This means it builds the symmetric
|
* given <code>set</code>. This means it builds the symmetric
|
||||||
* remainder of the two sets (the elements that are in one set,
|
* remainder of the two sets (the elements that are in one set,
|
||||||
* but not in the other). The result is stored into this bit set,
|
* but not in the other). The result is stored into this bit set,
|
||||||
* which grows as necessary.
|
* which grows as necessary.
|
||||||
* @param set the second bit set.
|
*
|
||||||
* @exception OutOfMemoryError if the current set can't grow.
|
* @param bs the second bit set
|
||||||
* @require set != null
|
* @throws NullPointerException if bs is null
|
||||||
*/
|
*/
|
||||||
public void xor(BitSet bs)
|
public void xor(BitSet bs)
|
||||||
{
|
{
|
||||||
ensure(bs.bits.length - 1);
|
ensure(bs.bits.length - 1);
|
||||||
int i;
|
for (int i = bs.bits.length - 1; i >= 0; i--)
|
||||||
for (i = 0; i < bs.bits.length; ++i)
|
|
||||||
bits[i] ^= bs.bits[i];
|
bits[i] ^= bs.bits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the vector is big enough.
|
/**
|
||||||
|
* Make sure the vector is big enough.
|
||||||
|
*
|
||||||
|
* @param lastElt the size needed for the bits array
|
||||||
|
*/
|
||||||
private final void ensure(int lastElt)
|
private final void ensure(int lastElt)
|
||||||
{
|
{
|
||||||
if (lastElt + 1 > bits.length)
|
if (lastElt >= bits.length)
|
||||||
{
|
{
|
||||||
long[] nd = new long[lastElt + 1];
|
long[] nd = new long[lastElt + 1];
|
||||||
System.arraycopy(bits, 0, nd, 0, bits.length);
|
System.arraycopy(bits, 0, nd, 0, bits.length);
|
||||||
bits = nd;
|
bits = nd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actual bits.
|
|
||||||
long[] bits;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 7997698588986878753L;
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
/* Dictionary.java -- an abstract (and essentially worthless)
|
/* Dictionary.java -- an abstract (and essentially worthless)
|
||||||
class which is Hashtable's superclass
|
class which is Hashtable's superclass
|
||||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
Copyright (C) 1998, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -35,49 +35,88 @@ package java.util;
|
||||||
* This is an abstract class which has really gone by the wayside.
|
* This is an abstract class which has really gone by the wayside.
|
||||||
* People at Javasoft are probably embarrassed by it. At this point,
|
* People at Javasoft are probably embarrassed by it. At this point,
|
||||||
* it might as well be an interface rather than a class, but it remains
|
* it might as well be an interface rather than a class, but it remains
|
||||||
* this poor, laugable skeleton for the sake of backwards compatibility.
|
* this poor, laughable skeleton for the sake of backwards compatibility.
|
||||||
* At any rate, this was what came before the <pre>Map</pre> interface
|
* At any rate, this was what came before the <pre>Map</pre> interface
|
||||||
* in the Collections framework.
|
* in the Collections framework.
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Map
|
||||||
|
* @see Hashtable
|
||||||
|
* @since 1.0
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public abstract class Dictionary extends Object
|
public abstract class Dictionary extends Object
|
||||||
{
|
{
|
||||||
/** returns an Enumeration of the values in this Dictionary */
|
/**
|
||||||
|
* Sole constructor (often called implicitly).
|
||||||
|
*/
|
||||||
|
public Dictionary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an Enumeration of the values in this Dictionary.
|
||||||
|
*
|
||||||
|
* @return an Enumeration of the values
|
||||||
|
* @see #keys()
|
||||||
|
*/
|
||||||
public abstract Enumeration elements();
|
public abstract Enumeration elements();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the value associated with the supplied key, or null
|
* Returns the value associated with the supplied key, or null
|
||||||
* if no such value exists
|
* if no such value exists. Since Dictionaries are not allowed null keys
|
||||||
|
* or elements, a null result always means the key is not present.
|
||||||
*
|
*
|
||||||
* @param key the key to use to fetch the value
|
* @param key the key to use to fetch the value
|
||||||
|
* @return the mapped value
|
||||||
|
* @throws NullPointerException if key is null
|
||||||
|
* @see #put(Object, Object)
|
||||||
*/
|
*/
|
||||||
public abstract Object get(Object key);
|
public abstract Object get(Object key);
|
||||||
|
|
||||||
/** returns true IFF there are no elements in this Dictionary (size() == 0) */
|
/**
|
||||||
|
* Returns true when there are no elements in this Dictionary.
|
||||||
|
*
|
||||||
|
* @return <code>size() == 0</code>
|
||||||
|
*/
|
||||||
public abstract boolean isEmpty();
|
public abstract boolean isEmpty();
|
||||||
|
|
||||||
/** returns an Enumeration of the keys in this Dictionary */
|
/**
|
||||||
|
* Returns an Enumeration of the keys in this Dictionary
|
||||||
|
*
|
||||||
|
* @return an Enumeration of the keys
|
||||||
|
* @see #elements()
|
||||||
|
*/
|
||||||
public abstract Enumeration keys();
|
public abstract Enumeration keys();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* inserts a new value into this Dictionary, located by the
|
* Inserts a new value into this Dictionary, located by the
|
||||||
* supllied key; note: Dictionary's subclasses (all 1 of them)
|
* supplied key. Dictionary does not support null keys or values, so
|
||||||
* do not support null keys or values (I can only assume this
|
* a null return can safely be interpreted as adding a new key.
|
||||||
* would have been more general)
|
|
||||||
*
|
*
|
||||||
* @param key the key which locates the value
|
* @param key the key which locates the value
|
||||||
* @param value the value to put into the Dictionary
|
* @param value the value to put into the Dictionary
|
||||||
|
* @return the previous value of the key, or null if there was none
|
||||||
|
* @throws NullPointerException if key or value is null
|
||||||
|
* @see #get(Object)
|
||||||
*/
|
*/
|
||||||
public abstract Object put(Object key, Object value);
|
public abstract Object put(Object key, Object value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes fro the Dictionary the value located by the given key
|
* Removes from the Dictionary the value located by the given key. A null
|
||||||
|
* return safely means that the key was not mapped in the Dictionary.
|
||||||
*
|
*
|
||||||
* @param key the key used to locate the value to be removed
|
* @param key the key used to locate the value to be removed
|
||||||
|
* @return the value associated with the removed key
|
||||||
|
* @throws NullPointerException if key is null
|
||||||
*/
|
*/
|
||||||
public abstract Object remove(Object key);
|
public abstract Object remove(Object key);
|
||||||
|
|
||||||
/** returns the number of values currently in this Dictionary */
|
/**
|
||||||
|
* Returns the number of values currently in this Dictionary.
|
||||||
|
*
|
||||||
|
* @return the number of keys in the Dictionary
|
||||||
|
*/
|
||||||
public abstract int size();
|
public abstract int size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,14 +53,16 @@ import java.io.ObjectOutputStream;
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* Under ideal circumstances (no collisions), HashMap offers O(1)
|
* Under ideal circumstances (no collisions), HashMap offers O(1)
|
||||||
* performance on most operations (<pre>containsValue()</pre> is,
|
* performance on most operations (<code>containsValue()</code> is,
|
||||||
* of course, O(n)). In the worst case (all keys map to the same
|
* of course, O(n)). In the worst case (all keys map to the same
|
||||||
* hash code -- very unlikely), most operations are O(n).
|
* hash code -- very unlikely), most operations are O(n).
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* HashMap is part of the JDK1.2 Collections API. It differs from
|
* HashMap is part of the JDK1.2 Collections API. It differs from
|
||||||
* Hashtable in that it accepts the null key and null values, and it
|
* Hashtable in that it accepts the null key and null values, and it
|
||||||
* does not support "Enumeration views."
|
* does not support "Enumeration views." Also, it is not synchronized;
|
||||||
|
* if you plan to use it in multiple threads, consider using:<br>
|
||||||
|
* <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The iterators are <i>fail-fast</i>, meaning that any structural
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
@ -81,6 +83,7 @@ import java.io.ObjectOutputStream;
|
||||||
* @see IdentityHashMap
|
* @see IdentityHashMap
|
||||||
* @see Hashtable
|
* @see Hashtable
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class HashMap extends AbstractMap
|
public class HashMap extends AbstractMap
|
||||||
implements Map, Cloneable, Serializable
|
implements Map, Cloneable, Serializable
|
||||||
|
@ -88,19 +91,16 @@ public class HashMap extends AbstractMap
|
||||||
/**
|
/**
|
||||||
* Default number of buckets. This is the value the JDK 1.3 uses. Some
|
* Default number of buckets. This is the value the JDK 1.3 uses. Some
|
||||||
* early documentation specified this value as 101. That is incorrect.
|
* early documentation specified this value as 101. That is incorrect.
|
||||||
|
* Package visible for use by HashSet.
|
||||||
*/
|
*/
|
||||||
static final int DEFAULT_CAPACITY = 11;
|
static final int DEFAULT_CAPACITY = 11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default load factor; this is explicitly specified by the spec.
|
* The default load factor; this is explicitly specified by the spec.
|
||||||
|
* Package visible for use by HashSet.
|
||||||
*/
|
*/
|
||||||
static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
static final float DEFAULT_LOAD_FACTOR = 0.75f;
|
||||||
|
|
||||||
/** "enum" of iterator types. */
|
|
||||||
static final int KEYS = 0,
|
|
||||||
VALUES = 1,
|
|
||||||
ENTRIES = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compatible with JDK 1.2.
|
* Compatible with JDK 1.2.
|
||||||
*/
|
*/
|
||||||
|
@ -108,41 +108,54 @@ public class HashMap extends AbstractMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The rounded product of the capacity and the load factor; when the number
|
* The rounded product of the capacity and the load factor; when the number
|
||||||
* of elements exceeds the threshold, the HashMap calls <pre>rehash()</pre>.
|
* of elements exceeds the threshold, the HashMap calls
|
||||||
* @serial
|
* <code>rehash()</code>.
|
||||||
|
* @serial the threshold for rehashing
|
||||||
*/
|
*/
|
||||||
int threshold;
|
private int threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load factor of this HashMap: used in computing the threshold.
|
* Load factor of this HashMap: used in computing the threshold.
|
||||||
* @serial
|
* Package visible for use by HashSet.
|
||||||
|
* @serial the load factor
|
||||||
*/
|
*/
|
||||||
final float loadFactor;
|
final float loadFactor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array containing the actual key-value mappings.
|
* Array containing the actual key-value mappings.
|
||||||
|
* Package visible for use by nested and subclasses.
|
||||||
*/
|
*/
|
||||||
transient HashEntry[] buckets;
|
transient HashEntry[] buckets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts the number of modifications this HashMap has undergone, used
|
* Counts the number of modifications this HashMap has undergone, used
|
||||||
* by Iterators to know when to throw ConcurrentModificationExceptions.
|
* by Iterators to know when to throw ConcurrentModificationExceptions.
|
||||||
|
* Package visible for use by nested and subclasses.
|
||||||
*/
|
*/
|
||||||
transient int modCount;
|
transient int modCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of this HashMap: denotes the number of key-value pairs.
|
* The size of this HashMap: denotes the number of key-value pairs.
|
||||||
|
* Package visible for use by nested and subclasses.
|
||||||
*/
|
*/
|
||||||
transient int size;
|
transient int size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to represent an entry in the hash table. Holds a single key-value
|
* The cache for {@link #entrySet()}.
|
||||||
* pair. This is extended again in LinkedHashMap. See {@link clone()}
|
|
||||||
* for why this must be Cloneable.
|
|
||||||
*/
|
*/
|
||||||
static class HashEntry extends BasicMapEntry implements Cloneable
|
private transient Set entries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to represent an entry in the hash table. Holds a single key-value
|
||||||
|
* pair. Package visible for use by subclass.
|
||||||
|
*
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
*/
|
||||||
|
static class HashEntry extends BasicMapEntry
|
||||||
{
|
{
|
||||||
/** The next entry in the linked list. */
|
/**
|
||||||
|
* The next entry in the linked list. Package visible for use by subclass.
|
||||||
|
*/
|
||||||
HashEntry next;
|
HashEntry next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,7 +171,8 @@ public class HashMap extends AbstractMap
|
||||||
/**
|
/**
|
||||||
* Called when this entry is removed from the map. This version simply
|
* Called when this entry is removed from the map. This version simply
|
||||||
* returns the value, but in LinkedHashMap, it must also do bookkeeping.
|
* returns the value, but in LinkedHashMap, it must also do bookkeeping.
|
||||||
* @return the value of this key as it is removed.
|
*
|
||||||
|
* @return the value of this key as it is removed
|
||||||
*/
|
*/
|
||||||
Object cleanup()
|
Object cleanup()
|
||||||
{
|
{
|
||||||
|
@ -182,9 +196,8 @@ public class HashMap extends AbstractMap
|
||||||
*
|
*
|
||||||
* Every element in Map m will be put into this new HashMap.
|
* Every element in Map m will be put into this new HashMap.
|
||||||
*
|
*
|
||||||
* @param m a Map whose key / value pairs will be put into
|
* @param m a Map whose key / value pairs will be put into the new HashMap.
|
||||||
* the new HashMap. <b>NOTE: key / value pairs
|
* <b>NOTE: key / value pairs are not cloned in this constructor.</b>
|
||||||
* are not cloned in this constructor.</b>
|
|
||||||
* @throws NullPointerException if m is null
|
* @throws NullPointerException if m is null
|
||||||
*/
|
*/
|
||||||
public HashMap(Map m)
|
public HashMap(Map m)
|
||||||
|
@ -197,8 +210,8 @@ public class HashMap extends AbstractMap
|
||||||
* Construct a new HashMap with a specific inital capacity and
|
* Construct a new HashMap with a specific inital capacity and
|
||||||
* default load factor of 0.75.
|
* default load factor of 0.75.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity of this HashMap (>=0)
|
* @param initialCapacity the initial capacity of this HashMap (>=0)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0)
|
* @throws IllegalArgumentException if (initialCapacity < 0)
|
||||||
*/
|
*/
|
||||||
public HashMap(int initialCapacity)
|
public HashMap(int initialCapacity)
|
||||||
{
|
{
|
||||||
|
@ -208,10 +221,10 @@ public class HashMap extends AbstractMap
|
||||||
/**
|
/**
|
||||||
* Construct a new HashMap with a specific inital capacity and load factor.
|
* Construct a new HashMap with a specific inital capacity and load factor.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity (>=0)
|
* @param initialCapacity the initial capacity (>=0)
|
||||||
* @param loadFactor the load factor (>0, not NaN)
|
* @param loadFactor the load factor (> 0, not NaN)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||||
* ! (loadFactor > 0.0)
|
* ! (loadFactor > 0.0)
|
||||||
*/
|
*/
|
||||||
public HashMap(int initialCapacity, float loadFactor)
|
public HashMap(int initialCapacity, float loadFactor)
|
||||||
{
|
{
|
||||||
|
@ -229,7 +242,8 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of kay-value mappings currently in this Map
|
* Returns the number of kay-value mappings currently in this Map.
|
||||||
|
*
|
||||||
* @return the size
|
* @return the size
|
||||||
*/
|
*/
|
||||||
public int size()
|
public int size()
|
||||||
|
@ -238,7 +252,8 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there are no key-value mappings currently in this Map
|
* Returns true if there are no key-value mappings currently in this Map.
|
||||||
|
*
|
||||||
* @return <code>size() == 0</code>
|
* @return <code>size() == 0</code>
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty()
|
public boolean isEmpty()
|
||||||
|
@ -246,52 +261,9 @@ public class HashMap extends AbstractMap
|
||||||
return size == 0;
|
return size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this HashMap contains a value <pre>o</pre>, such that
|
|
||||||
* <pre>o.equals(value)</pre>.
|
|
||||||
*
|
|
||||||
* @param value the value to search for in this HashMap
|
|
||||||
* @return true if at least one key maps to the value
|
|
||||||
*/
|
|
||||||
public boolean containsValue(Object value)
|
|
||||||
{
|
|
||||||
for (int i = buckets.length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
HashEntry e = buckets[i];
|
|
||||||
while (e != null)
|
|
||||||
{
|
|
||||||
if (value == null ? e.value == null : value.equals(e.value))
|
|
||||||
return true;
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the supplied object <pre>equals()</pre> a key
|
|
||||||
* in this HashMap.
|
|
||||||
*
|
|
||||||
* @param key the key to search for in this HashMap
|
|
||||||
* @return true if the key is in the table
|
|
||||||
* @see #containsValue(Object)
|
|
||||||
*/
|
|
||||||
public boolean containsKey(Object key)
|
|
||||||
{
|
|
||||||
int idx = hash(key);
|
|
||||||
HashEntry e = buckets[idx];
|
|
||||||
while (e != null)
|
|
||||||
{
|
|
||||||
if (key == null ? e.key == null : key.equals(e.key))
|
|
||||||
return true;
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value in this HashMap associated with the supplied key,
|
* Return the value in this HashMap associated with the supplied key,
|
||||||
* or <pre>null</pre> if the key maps to nothing. NOTE: Since the value
|
* or <code>null</code> if the key maps to nothing. NOTE: Since the value
|
||||||
* could also be null, you must use containsKey to see if this key
|
* could also be null, you must use containsKey to see if this key
|
||||||
* actually maps to something.
|
* actually maps to something.
|
||||||
*
|
*
|
||||||
|
@ -306,13 +278,34 @@ public class HashMap extends AbstractMap
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (key == null ? e.key == null : key.equals(e.key))
|
if (equals(key, e.key))
|
||||||
return e.value;
|
return e.value;
|
||||||
e = e.next;
|
e = e.next;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the supplied object <code>equals()</code> a key
|
||||||
|
* in this HashMap.
|
||||||
|
*
|
||||||
|
* @param key the key to search for in this HashMap
|
||||||
|
* @return true if the key is in the table
|
||||||
|
* @see #containsValue(Object)
|
||||||
|
*/
|
||||||
|
public boolean containsKey(Object key)
|
||||||
|
{
|
||||||
|
int idx = hash(key);
|
||||||
|
HashEntry e = buckets[idx];
|
||||||
|
while (e != null)
|
||||||
|
{
|
||||||
|
if (equals(key, e.key))
|
||||||
|
return true;
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts the supplied value into the Map, mapped by the supplied key.
|
* Puts the supplied value into the Map, mapped by the supplied key.
|
||||||
* The value may be retrieved by any object which <code>equals()</code>
|
* The value may be retrieved by any object which <code>equals()</code>
|
||||||
|
@ -328,13 +321,12 @@ public class HashMap extends AbstractMap
|
||||||
*/
|
*/
|
||||||
public Object put(Object key, Object value)
|
public Object put(Object key, Object value)
|
||||||
{
|
{
|
||||||
modCount++;
|
|
||||||
int idx = hash(key);
|
int idx = hash(key);
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
|
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (key == null ? e.key == null : key.equals(e.key))
|
if (equals(key, e.key))
|
||||||
// Must use this method for necessary bookkeeping in LinkedHashMap.
|
// Must use this method for necessary bookkeeping in LinkedHashMap.
|
||||||
return e.setValue(value);
|
return e.setValue(value);
|
||||||
else
|
else
|
||||||
|
@ -342,6 +334,7 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, we know we need to add a new entry.
|
// At this point, we know we need to add a new entry.
|
||||||
|
modCount++;
|
||||||
if (++size > threshold)
|
if (++size > threshold)
|
||||||
{
|
{
|
||||||
rehash();
|
rehash();
|
||||||
|
@ -354,59 +347,6 @@ public class HashMap extends AbstractMap
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method for put, that creates and adds a new Entry. This is
|
|
||||||
* overridden in LinkedHashMap for bookkeeping purposes.
|
|
||||||
*
|
|
||||||
* @param key the key of the new Entry
|
|
||||||
* @param value the value
|
|
||||||
* @param idx the index in buckets where the new Entry belongs
|
|
||||||
* @param callRemove Whether to call the removeEldestEntry method.
|
|
||||||
* @see #put(Object, Object)
|
|
||||||
*/
|
|
||||||
void addEntry(Object key, Object value, int idx, boolean callRemove)
|
|
||||||
{
|
|
||||||
HashEntry e = new HashEntry(key, value);
|
|
||||||
|
|
||||||
e.next = buckets[idx];
|
|
||||||
buckets[idx] = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes from the HashMap and returns the value which is mapped by the
|
|
||||||
* supplied key. If the key maps to nothing, then the HashMap remains
|
|
||||||
* unchanged, and <pre>null</pre> is returned. NOTE: Since the value
|
|
||||||
* could also be null, you must use containsKey to see if you are
|
|
||||||
* actually removing a mapping.
|
|
||||||
*
|
|
||||||
* @param key the key used to locate the value to remove
|
|
||||||
* @return whatever the key mapped to, if present
|
|
||||||
*/
|
|
||||||
public Object remove(Object key)
|
|
||||||
{
|
|
||||||
modCount++;
|
|
||||||
int idx = hash(key);
|
|
||||||
HashEntry e = buckets[idx];
|
|
||||||
HashEntry last = null;
|
|
||||||
|
|
||||||
while (e != null)
|
|
||||||
{
|
|
||||||
if (key == null ? e.key == null : key.equals(e.key))
|
|
||||||
{
|
|
||||||
if (last == null)
|
|
||||||
buckets[idx] = e.next;
|
|
||||||
else
|
|
||||||
last.next = e.next;
|
|
||||||
size--;
|
|
||||||
// Method call necessary for LinkedHashMap to work correctly.
|
|
||||||
return e.cleanup();
|
|
||||||
}
|
|
||||||
last = e;
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies all elements of the given map into this hashtable. If this table
|
* Copies all elements of the given map into this hashtable. If this table
|
||||||
* already has a mapping for a key, the new mapping replaces the current
|
* already has a mapping for a key, the new mapping replaces the current
|
||||||
|
@ -434,14 +374,75 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes from the HashMap and returns the value which is mapped by the
|
||||||
|
* supplied key. If the key maps to nothing, then the HashMap remains
|
||||||
|
* unchanged, and <code>null</code> is returned. NOTE: Since the value
|
||||||
|
* could also be null, you must use containsKey to see if you are
|
||||||
|
* actually removing a mapping.
|
||||||
|
*
|
||||||
|
* @param key the key used to locate the value to remove
|
||||||
|
* @return whatever the key mapped to, if present
|
||||||
|
*/
|
||||||
|
public Object remove(Object key)
|
||||||
|
{
|
||||||
|
int idx = hash(key);
|
||||||
|
HashEntry e = buckets[idx];
|
||||||
|
HashEntry last = null;
|
||||||
|
|
||||||
|
while (e != null)
|
||||||
|
{
|
||||||
|
if (equals(key, e.key))
|
||||||
|
{
|
||||||
|
modCount++;
|
||||||
|
if (last == null)
|
||||||
|
buckets[idx] = e.next;
|
||||||
|
else
|
||||||
|
last.next = e.next;
|
||||||
|
size--;
|
||||||
|
// Method call necessary for LinkedHashMap to work correctly.
|
||||||
|
return e.cleanup();
|
||||||
|
}
|
||||||
|
last = e;
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the Map so it has no keys. This is O(1).
|
* Clears the Map so it has no keys. This is O(1).
|
||||||
*/
|
*/
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
modCount++;
|
if (size != 0)
|
||||||
Arrays.fill(buckets, null);
|
{
|
||||||
size = 0;
|
modCount++;
|
||||||
|
Arrays.fill(buckets, null);
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this HashMap contains a value <code>o</code>, such that
|
||||||
|
* <code>o.equals(value)</code>.
|
||||||
|
*
|
||||||
|
* @param value the value to search for in this HashMap
|
||||||
|
* @return true if at least one key maps to the value
|
||||||
|
* @see containsKey(Object)
|
||||||
|
*/
|
||||||
|
public boolean containsValue(Object value)
|
||||||
|
{
|
||||||
|
for (int i = buckets.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
HashEntry e = buckets[i];
|
||||||
|
while (e != null)
|
||||||
|
{
|
||||||
|
if (equals(value, e.value))
|
||||||
|
return true;
|
||||||
|
e = e.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -463,6 +464,8 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
copy.buckets = new HashEntry[buckets.length];
|
copy.buckets = new HashEntry[buckets.length];
|
||||||
copy.putAllInternal(this);
|
copy.putAllInternal(this);
|
||||||
|
// Clear the entry cache. AbstractMap.clone() does the others.
|
||||||
|
copy.entries = null;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,41 +480,43 @@ public class HashMap extends AbstractMap
|
||||||
*/
|
*/
|
||||||
public Set keySet()
|
public Set keySet()
|
||||||
{
|
{
|
||||||
// Create an AbstractSet with custom implementations of those methods that
|
if (keys == null)
|
||||||
// can be overridden easily and efficiently.
|
// Create an AbstractSet with custom implementations of those methods
|
||||||
return new AbstractSet()
|
// that can be overridden easily and efficiently.
|
||||||
{
|
keys = new AbstractSet()
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
public int size()
|
||||||
}
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||||
return HashMap.this.iterator(KEYS);
|
return HashMap.this.iterator(KEYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
HashMap.this.clear();
|
HashMap.this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object o)
|
public boolean contains(Object o)
|
||||||
{
|
{
|
||||||
return HashMap.this.containsKey(o);
|
return containsKey(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object o)
|
public boolean remove(Object o)
|
||||||
{
|
{
|
||||||
// Test against the size of the HashMap to determine if anything
|
// Test against the size of the HashMap to determine if anything
|
||||||
// really got removed. This is necessary because the return value of
|
// really got removed. This is neccessary because the return value
|
||||||
// HashMap.remove() is ambiguous in the null case.
|
// of HashMap.remove() is ambiguous in the null case.
|
||||||
int oldsize = size;
|
int oldsize = size;
|
||||||
HashMap.this.remove(o);
|
HashMap.this.remove(o);
|
||||||
return (oldsize != size);
|
return oldsize != size;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -526,33 +531,34 @@ public class HashMap extends AbstractMap
|
||||||
*/
|
*/
|
||||||
public Collection values()
|
public Collection values()
|
||||||
{
|
{
|
||||||
// We don't bother overriding many of the optional methods, as doing so
|
if (values == null)
|
||||||
// wouldn't provide any significant performance advantage.
|
// We don't bother overriding many of the optional methods, as doing so
|
||||||
return new AbstractCollection()
|
// wouldn't provide any significant performance advantage.
|
||||||
{
|
values = new AbstractCollection()
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
public int size()
|
||||||
}
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||||
return HashMap.this.iterator(VALUES);
|
return HashMap.this.iterator(VALUES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
HashMap.this.clear();
|
HashMap.this.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a "set view" of this HashMap's entries. The set is backed by
|
* Returns a "set view" of this HashMap's entries. The set is backed by
|
||||||
* the HashMap, so changes in one show up in the other. The set supports
|
* the HashMap, so changes in one show up in the other. The set supports
|
||||||
* element removal, but not element addition.
|
* element removal, but not element addition.<p>
|
||||||
* <p>
|
|
||||||
*
|
*
|
||||||
* Note that the iterators for all three views, from keySet(), entrySet(),
|
* Note that the iterators for all three views, from keySet(), entrySet(),
|
||||||
* and values(), traverse the HashMap in the same sequence.
|
* and values(), traverse the HashMap in the same sequence.
|
||||||
|
@ -564,53 +570,62 @@ public class HashMap extends AbstractMap
|
||||||
*/
|
*/
|
||||||
public Set entrySet()
|
public Set entrySet()
|
||||||
{
|
{
|
||||||
// Create an AbstractSet with custom implementations of those methods that
|
if (entries == null)
|
||||||
// can be overridden easily and efficiently.
|
// Create an AbstractSet with custom implementations of those methods
|
||||||
return new AbstractSet()
|
// that can be overridden easily and efficiently.
|
||||||
{
|
entries = new AbstractSet()
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
public int size()
|
||||||
}
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
// Cannot create the iterator directly, because of LinkedHashMap.
|
// Cannot create the iterator directly, because of LinkedHashMap.
|
||||||
return HashMap.this.iterator(ENTRIES);
|
return HashMap.this.iterator(ENTRIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
HashMap.this.clear();
|
HashMap.this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object o)
|
public boolean contains(Object o)
|
||||||
{
|
{
|
||||||
return getEntry(o) != null;
|
return getEntry(o) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(Object o)
|
public boolean remove(Object o)
|
||||||
{
|
{
|
||||||
HashEntry e = getEntry(o);
|
HashEntry e = getEntry(o);
|
||||||
if (e != null)
|
if (e != null)
|
||||||
{
|
{
|
||||||
HashMap.this.remove(e.key);
|
HashMap.this.remove(e.key);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper method that returns an index in the buckets array for `key;
|
/**
|
||||||
* based on its hashCode().
|
* Helper method for put, that creates and adds a new Entry. This is
|
||||||
|
* overridden in LinkedHashMap for bookkeeping purposes.
|
||||||
*
|
*
|
||||||
* @param key the key
|
* @param key the key of the new Entry
|
||||||
* @return the bucket number
|
* @param value the value
|
||||||
|
* @param idx the index in buckets where the new Entry belongs
|
||||||
|
* @param callRemove whether to call the removeEldestEntry method
|
||||||
|
* @see #put(Object, Object)
|
||||||
*/
|
*/
|
||||||
int hash(Object key)
|
void addEntry(Object key, Object value, int idx, boolean callRemove)
|
||||||
{
|
{
|
||||||
return (key == null) ? 0 : Math.abs(key.hashCode() % buckets.length);
|
HashEntry e = new HashEntry(key, value);
|
||||||
|
|
||||||
|
e.next = buckets[idx];
|
||||||
|
buckets[idx] = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -637,6 +652,52 @@ public class HashMap extends AbstractMap
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that returns an index in the buckets array for `key'
|
||||||
|
* based on its hashCode(). Package visible for use by subclasses.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @return the bucket number
|
||||||
|
*/
|
||||||
|
final int hash(Object key)
|
||||||
|
{
|
||||||
|
return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a parameterized iterator. Must be overrideable, since
|
||||||
|
* LinkedHashMap iterates in a different order.
|
||||||
|
*
|
||||||
|
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
|
||||||
|
* @return the appropriate iterator
|
||||||
|
*/
|
||||||
|
Iterator iterator(int type)
|
||||||
|
{
|
||||||
|
return new HashIterator(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simplified, more efficient internal implementation of putAll(). The
|
||||||
|
* Map constructor and clone() should not call putAll or put, in order to
|
||||||
|
* be compatible with the JDK implementation with respect to subclasses.
|
||||||
|
*
|
||||||
|
* @param m the map to initialize this from
|
||||||
|
*/
|
||||||
|
void putAllInternal(Map m)
|
||||||
|
{
|
||||||
|
Iterator itr = m.entrySet().iterator();
|
||||||
|
int msize = m.size();
|
||||||
|
this.size = msize;
|
||||||
|
|
||||||
|
for (; msize > 0; msize--)
|
||||||
|
{
|
||||||
|
Map.Entry e = (Map.Entry) itr.next();
|
||||||
|
Object key = e.getKey();
|
||||||
|
int idx = hash(key);
|
||||||
|
addEntry(key, e.getValue(), idx, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the size of the HashMap and rehashes all keys to new array
|
* Increases the size of the HashMap and rehashes all keys to new array
|
||||||
* indices; this is called when the addition of a new value would cause
|
* indices; this is called when the addition of a new value would cause
|
||||||
|
@ -681,35 +742,6 @@ public class HashMap extends AbstractMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a parameterized iterator. Must be overrideable, since
|
|
||||||
* LinkedHashMap iterates in a different order.
|
|
||||||
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
|
|
||||||
* @return the appropriate iterator
|
|
||||||
*/
|
|
||||||
Iterator iterator(int type)
|
|
||||||
{
|
|
||||||
return new HashIterator(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simplified, more efficient internal implementation of putAll(). The
|
|
||||||
* Map constructor and clone() should not call putAll or put, in order to
|
|
||||||
* be compatible with the JDK implementation with respect to subclasses.
|
|
||||||
*/
|
|
||||||
void putAllInternal(Map m)
|
|
||||||
{
|
|
||||||
Iterator itr = m.entrySet().iterator();
|
|
||||||
|
|
||||||
for (int msize = m.size(); msize > 0; msize--)
|
|
||||||
{
|
|
||||||
Map.Entry e = (Map.Entry) itr.next();
|
|
||||||
Object key = e.getKey();
|
|
||||||
int idx = hash(key);
|
|
||||||
addEntry(key, e.getValue(), idx, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes this object to the given stream.
|
* Serializes this object to the given stream.
|
||||||
*
|
*
|
||||||
|
@ -757,9 +789,6 @@ public class HashMap extends AbstractMap
|
||||||
// Read and use capacity.
|
// Read and use capacity.
|
||||||
buckets = new HashEntry[s.readInt()];
|
buckets = new HashEntry[s.readInt()];
|
||||||
int len = s.readInt();
|
int len = s.readInt();
|
||||||
// Already happens automatically.
|
|
||||||
// size = 0;
|
|
||||||
// modCount = 0;
|
|
||||||
|
|
||||||
// Read and use key/value pairs.
|
// Read and use key/value pairs.
|
||||||
for ( ; len > 0; len--)
|
for ( ; len > 0; len--)
|
||||||
|
@ -773,29 +802,29 @@ public class HashMap extends AbstractMap
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
*/
|
*/
|
||||||
class HashIterator implements Iterator
|
private final class HashIterator implements Iterator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
|
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
|
||||||
* or {@link #ENTRIES}.
|
* or {@link #ENTRIES}.
|
||||||
*/
|
*/
|
||||||
final int type;
|
private final int type;
|
||||||
/**
|
/**
|
||||||
* The number of modifications to the backing HashMap that we know about.
|
* The number of modifications to the backing HashMap that we know about.
|
||||||
*/
|
*/
|
||||||
int knownMod = modCount;
|
private int knownMod = modCount;
|
||||||
/** The number of elements remaining to be returned by next(). */
|
/** The number of elements remaining to be returned by next(). */
|
||||||
int count = size;
|
private int count = size;
|
||||||
/** Current index in the physical hash table. */
|
/** Current index in the physical hash table. */
|
||||||
int idx = buckets.length;
|
private int idx = buckets.length;
|
||||||
/** The last Entry returned by a next() call. */
|
/** The last Entry returned by a next() call. */
|
||||||
HashEntry last;
|
private HashEntry last;
|
||||||
/**
|
/**
|
||||||
* The next entry that should be returned by next(). It is set to something
|
* The next entry that should be returned by next(). It is set to something
|
||||||
* if we're iterating through a bucket that contains multiple linked
|
* if we're iterating through a bucket that contains multiple linked
|
||||||
* entries. It is null if next() needs to find a new bucket.
|
* entries. It is null if next() needs to find a new bucket.
|
||||||
*/
|
*/
|
||||||
HashEntry next;
|
private HashEntry next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new HashIterator with the supplied type.
|
* Construct a new HashIterator with the supplied type.
|
||||||
|
@ -840,14 +869,14 @@ public class HashMap extends AbstractMap
|
||||||
last = e;
|
last = e;
|
||||||
if (type == VALUES)
|
if (type == VALUES)
|
||||||
return e.value;
|
return e.value;
|
||||||
else if (type == KEYS)
|
if (type == KEYS)
|
||||||
return e.key;
|
return e.key;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes from the backing HashMap the last element which was fetched
|
* Removes from the backing HashMap the last element which was fetched
|
||||||
* with the <pre>next()</pre> method.
|
* with the <code>next()</code> method.
|
||||||
* @throws ConcurrentModificationException if the HashMap was modified
|
* @throws ConcurrentModificationException if the HashMap was modified
|
||||||
* @throws IllegalStateException if called when there is no last element
|
* @throws IllegalStateException if called when there is no last element
|
||||||
*/
|
*/
|
||||||
|
@ -859,8 +888,8 @@ public class HashMap extends AbstractMap
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
HashMap.this.remove(last.key);
|
HashMap.this.remove(last.key);
|
||||||
knownMod++;
|
|
||||||
last = null;
|
last = null;
|
||||||
|
knownMod++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* HashSet.java -- a class providing a HashMap-backet Set
|
/* HashSet.java -- a class providing a HashMap-backed Set
|
||||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
@ -33,87 +33,115 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides a HashMap-backed implementation of the
|
* This class provides a HashMap-backed implementation of the Set interface.
|
||||||
* Set interface.
|
* <p>
|
||||||
*
|
|
||||||
* Each element in the Set is a key in the backing HashMap; each key
|
|
||||||
* maps to a static token, denoting that the key does, in fact, exist.
|
|
||||||
*
|
*
|
||||||
* Most operations are O(1), assuming no hash collisions. In the worst
|
* Most operations are O(1), assuming no hash collisions. In the worst
|
||||||
* case (where all hases collide), operations are O(n).
|
* case (where all hashes collide), operations are O(n). Setting the
|
||||||
|
* initial capacity too low will force many resizing operations, but
|
||||||
|
* setting the initial capacity too high (or loadfactor too low) leads
|
||||||
|
* to wasted memory and slower iteration.
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* HashSet is a part of the JDK1.2 Collections API.
|
* HashSet accepts the null key and null values. It is not synchronized,
|
||||||
|
* so if you need multi-threaded access, consider using:<br>
|
||||||
|
* <code>Set s = Collections.synchronizedSet(new HashSet(...));</code>
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
* modification, except for <code>remove()</code> called on the iterator
|
||||||
|
* itself, cause the iterator to throw a
|
||||||
|
* {@link ConcurrentModificationException} rather than exhibit
|
||||||
|
* non-deterministic behavior.
|
||||||
|
*
|
||||||
|
* @author Jon Zeppieri
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see Set
|
||||||
|
* @see TreeSet
|
||||||
|
* @see Collections#synchronizedSet(Set)
|
||||||
|
* @see HashMap
|
||||||
|
* @see LinkedHashSet
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class HashSet extends AbstractSet
|
public class HashSet extends AbstractSet
|
||||||
implements Set, Cloneable, Serializable
|
implements Set, Cloneable, Serializable
|
||||||
{
|
{
|
||||||
/** the HashMap which backs this Set */
|
/**
|
||||||
transient HashMap map;
|
* Compatible with JDK 1.2.
|
||||||
static final long serialVersionUID = -5024744406713321676L;
|
*/
|
||||||
|
private static final long serialVersionUID = -5024744406713321676L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* construct a new, empty HashSet whose backing HashMap has the default
|
* The HashMap which backs this Set.
|
||||||
* capacity and loadFacor
|
*/
|
||||||
|
private transient HashMap map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new, empty HashSet whose backing HashMap has the default
|
||||||
|
* capacity (11) and loadFacor (0.75).
|
||||||
*/
|
*/
|
||||||
public HashSet()
|
public HashSet()
|
||||||
{
|
{
|
||||||
map = new HashMap();
|
this(HashMap.DEFAULT_CAPACITY, HashMap.DEFAULT_LOAD_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* construct a new, empty HashSet whose backing HashMap has the supplied
|
* Construct a new, empty HashSet whose backing HashMap has the supplied
|
||||||
* capacity and the default load factor
|
* capacity and the default load factor (0.75).
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity of the backing
|
* @param initialCapacity the initial capacity of the backing HashMap
|
||||||
* HashMap
|
* @throws IllegalArgumentException if the capacity is negative
|
||||||
*/
|
*/
|
||||||
public HashSet(int initialCapacity)
|
public HashSet(int initialCapacity)
|
||||||
{
|
{
|
||||||
map = new HashMap(initialCapacity);
|
this(initialCapacity, HashMap.DEFAULT_LOAD_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* construct a new, empty HashSet whose backing HashMap has the supplied
|
* Construct a new, empty HashSet whose backing HashMap has the supplied
|
||||||
* capacity and load factor
|
* capacity and load factor.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity of the backing
|
* @param initialCapacity the initial capacity of the backing HashMap
|
||||||
* HashMap
|
* @param loadFactor the load factor of the backing HashMap
|
||||||
* @param loadFactor the load factor of the backing HashMap
|
* @throws IllegalArgumentException if either argument is negative, or
|
||||||
|
* if loadFactor is POSITIVE_INFINITY or NaN
|
||||||
*/
|
*/
|
||||||
public HashSet(int initialCapacity, float loadFactor)
|
public HashSet(int initialCapacity, float loadFactor)
|
||||||
{
|
{
|
||||||
map = new HashMap(initialCapacity, loadFactor);
|
map = init(initialCapacity, loadFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* construct a new HashSet with the same elements as are in the supplied
|
* Construct a new HashSet with the same elements as are in the supplied
|
||||||
* collection (eliminating any duplicates, of course; the backing HashMap
|
* collection (eliminating any duplicates, of course). The backing storage
|
||||||
* will have the default capacity and load factor
|
* has twice the size of the collection, or the default size of 11,
|
||||||
|
* whichever is greater; and the default load factor (0.75).
|
||||||
*
|
*
|
||||||
* @param c a collection containing the elements with
|
* @param c a collection of initial set elements
|
||||||
* which this set will be initialized
|
* @throws NullPointerException if c is null
|
||||||
*/
|
*/
|
||||||
public HashSet(Collection c)
|
public HashSet(Collection c)
|
||||||
{
|
{
|
||||||
map = new HashMap();
|
this(Math.max(2 * c.size(), HashMap.DEFAULT_CAPACITY));
|
||||||
addAll(c);
|
addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds the given Object to the set if it is not already in the Set,
|
* Adds the given Object to the set if it is not already in the Set.
|
||||||
* returns true if teh element was added, false otherwise
|
* This set permits a null element.
|
||||||
*
|
*
|
||||||
* @param o the Object to add to this Set
|
* @param o the Object to add to this Set
|
||||||
|
* @return true if the set did not already contain o
|
||||||
*/
|
*/
|
||||||
public boolean add(Object o)
|
public boolean add(Object o)
|
||||||
{
|
{
|
||||||
return (map.put(o, Boolean.TRUE) == null);
|
return map.put(o, "") == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* empties this Set of all elements; this is a fast operation [O(1)]
|
* Empties this Set of all elements; this takes constant time.
|
||||||
*/
|
*/
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
|
@ -121,53 +149,67 @@ public class HashSet extends AbstractSet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns a shallow copy of this Set (the Set itself is cloned; its
|
* Returns a shallow copy of this Set. The Set itself is cloned; its
|
||||||
* elements are not)
|
* elements are not.
|
||||||
|
*
|
||||||
|
* @return a shallow clone of the set
|
||||||
*/
|
*/
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
HashSet copy = null;
|
HashSet copy = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
copy = (HashSet) super.clone();
|
copy = (HashSet) super.clone();
|
||||||
}
|
}
|
||||||
catch (CloneNotSupportedException x)
|
catch (CloneNotSupportedException x)
|
||||||
{
|
{
|
||||||
|
// Impossible to get here.
|
||||||
}
|
}
|
||||||
copy.map = (HashMap) map.clone();
|
copy.map = (HashMap) map.clone();
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns true if the supplied element is in this Set, false otherwise
|
* Returns true if the supplied element is in this Set.
|
||||||
*
|
*
|
||||||
* @param o the Object whose presence in this Set we are testing for
|
* @param o the Object to look for
|
||||||
|
* @return true if it is in the set
|
||||||
*/
|
*/
|
||||||
public boolean contains(Object o)
|
public boolean contains(Object o)
|
||||||
{
|
{
|
||||||
return map.containsKey(o);
|
return map.containsKey(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns true if this set has no elements in it (size() == 0)
|
* Returns true if this set has no elements in it.
|
||||||
|
*
|
||||||
|
* @return <code>size() == 0</code>.
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty()
|
public boolean isEmpty()
|
||||||
{
|
{
|
||||||
return map.isEmpty();
|
return map.size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns an Iterator over the elements of this Set; the Iterator allows
|
* Returns an Iterator over the elements of this Set, which visits the
|
||||||
* removal of elements
|
* elements in no particular order. For this class, the Iterator allows
|
||||||
|
* removal of elements. The iterator is fail-fast, and will throw a
|
||||||
|
* ConcurrentModificationException if the set is modified externally.
|
||||||
|
*
|
||||||
|
* @return a set iterator
|
||||||
|
* @see ConcurrentModificationException
|
||||||
*/
|
*/
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return map.keySet().iterator();
|
// Avoid creating intermediate keySet() object by using non-public API.
|
||||||
|
return map.iterator(HashMap.KEYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes the supplied Object from this Set if it is in the Set; returns
|
* Removes the supplied Object from this Set if it is in the Set.
|
||||||
* true if an element was removed, false otherwise
|
*
|
||||||
|
* @param o the object to remove
|
||||||
|
* @return true if an element was removed
|
||||||
*/
|
*/
|
||||||
public boolean remove(Object o)
|
public boolean remove(Object o)
|
||||||
{
|
{
|
||||||
|
@ -175,18 +217,42 @@ public class HashSet extends AbstractSet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the number of elements in this Set
|
* Returns the number of elements in this Set (its cardinality).
|
||||||
|
*
|
||||||
|
* @return the size of the set
|
||||||
*/
|
*/
|
||||||
public int size()
|
public int size()
|
||||||
{
|
{
|
||||||
return map.size();
|
return map.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Serialize this Object in a manner which is binary-compatible with the
|
/**
|
||||||
* JDK */
|
* Helper method which initializes the backing Map. Overridden by
|
||||||
|
* LinkedHashSet for correct semantics.
|
||||||
|
*
|
||||||
|
* @param capacity the initial capacity
|
||||||
|
* @param load the initial load factor
|
||||||
|
* @return the backing HashMap
|
||||||
|
*/
|
||||||
|
HashMap init(int capacity, float load)
|
||||||
|
{
|
||||||
|
return new HashMap(capacity, load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes this object to the given stream.
|
||||||
|
*
|
||||||
|
* @param s the stream to write to
|
||||||
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
|
||||||
|
* of the backing store, followed by the set size (int),
|
||||||
|
* then a listing of its elements (Object) in no order
|
||||||
|
*/
|
||||||
private void writeObject(ObjectOutputStream s) throws IOException
|
private void writeObject(ObjectOutputStream s) throws IOException
|
||||||
{
|
{
|
||||||
Iterator it = iterator();
|
s.defaultWriteObject();
|
||||||
|
// Avoid creating intermediate keySet() object by using non-public API.
|
||||||
|
Iterator it = map.iterator(HashMap.KEYS);
|
||||||
s.writeInt(map.buckets.length);
|
s.writeInt(map.buckets.length);
|
||||||
s.writeFloat(map.loadFactor);
|
s.writeFloat(map.loadFactor);
|
||||||
s.writeInt(map.size);
|
s.writeInt(map.size);
|
||||||
|
@ -194,25 +260,23 @@ public class HashSet extends AbstractSet
|
||||||
s.writeObject(it.next());
|
s.writeObject(it.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deserialize this Object in a manner which is binary-compatible with
|
/**
|
||||||
* the JDK */
|
* Deserializes this object from the given stream.
|
||||||
private void readObject(ObjectInputStream s) throws IOException,
|
*
|
||||||
ClassNotFoundException
|
* @param s the stream to read from
|
||||||
|
* @throws ClassNotFoundException if the underlying stream fails
|
||||||
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the <i>capacity</i> (int) and <i>loadFactor</i> (float)
|
||||||
|
* of the backing store, followed by the set size (int),
|
||||||
|
* then a listing of its elements (Object) in no order
|
||||||
|
*/
|
||||||
|
private void readObject(ObjectInputStream s)
|
||||||
|
throws IOException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
int i, size, capacity;
|
s.defaultReadObject();
|
||||||
float loadFactor;
|
|
||||||
Object element;
|
|
||||||
|
|
||||||
capacity = s.readInt();
|
map = init(s.readInt(), s.readFloat());
|
||||||
loadFactor = s.readFloat();
|
for (int size = s.readInt(); size > 0; size--)
|
||||||
size = s.readInt();
|
map.put(s.readObject(), "");
|
||||||
|
|
||||||
map = new HashMap(capacity, loadFactor);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
element = s.readObject();
|
|
||||||
map.put(element, Boolean.TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,9 @@ import java.io.ObjectOutputStream;
|
||||||
* Unlike HashMap, Hashtable does not accept `null' as a key value. Also,
|
* Unlike HashMap, Hashtable does not accept `null' as a key value. Also,
|
||||||
* all accesses are synchronized: in a single thread environment, this is
|
* all accesses are synchronized: in a single thread environment, this is
|
||||||
* expensive, but in a multi-thread environment, this saves you the effort
|
* expensive, but in a multi-thread environment, this saves you the effort
|
||||||
* of extra synchronization.
|
* of extra synchronization. However, the old-style enumerators are not
|
||||||
|
* synchronized, because they can lead to unspecified behavior even if
|
||||||
|
* they were synchronized. You have been warned.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The iterators are <i>fail-fast</i>, meaning that any structural
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
@ -84,6 +86,7 @@ import java.io.ObjectOutputStream;
|
||||||
* @see IdentityHashMap
|
* @see IdentityHashMap
|
||||||
* @see LinkedHashMap
|
* @see LinkedHashMap
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class Hashtable extends Dictionary
|
public class Hashtable extends Dictionary
|
||||||
implements Map, Cloneable, Serializable
|
implements Map, Cloneable, Serializable
|
||||||
|
@ -93,6 +96,12 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
private static final int DEFAULT_CAPACITY = 11;
|
private static final int DEFAULT_CAPACITY = 11;
|
||||||
|
|
||||||
|
/** An "enum" of iterator types. */
|
||||||
|
// Package visible for use by nested classes.
|
||||||
|
static final int KEYS = 0,
|
||||||
|
VALUES = 1,
|
||||||
|
ENTRIES = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default load factor; this is explicitly specified by the spec.
|
* The default load factor; this is explicitly specified by the spec.
|
||||||
*/
|
*/
|
||||||
|
@ -106,39 +115,57 @@ public class Hashtable extends Dictionary
|
||||||
/**
|
/**
|
||||||
* The rounded product of the capacity and the load factor; when the number
|
* The rounded product of the capacity and the load factor; when the number
|
||||||
* of elements exceeds the threshold, the Hashtable calls
|
* of elements exceeds the threshold, the Hashtable calls
|
||||||
* <pre>rehash()</pre>.
|
* <code>rehash()</code>.
|
||||||
* @serial
|
* @serial
|
||||||
*/
|
*/
|
||||||
int threshold;
|
private int threshold;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load factor of this Hashtable: used in computing the threshold.
|
* Load factor of this Hashtable: used in computing the threshold.
|
||||||
* @serial
|
* @serial
|
||||||
*/
|
*/
|
||||||
final float loadFactor;
|
private final float loadFactor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array containing the actual key-value mappings.
|
* Array containing the actual key-value mappings.
|
||||||
*/
|
*/
|
||||||
|
// Package visible for use by nested classes.
|
||||||
transient HashEntry[] buckets;
|
transient HashEntry[] buckets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts the number of modifications this Hashtable has undergone, used
|
* Counts the number of modifications this Hashtable has undergone, used
|
||||||
* by Iterators to know when to throw ConcurrentModificationExceptions.
|
* by Iterators to know when to throw ConcurrentModificationExceptions.
|
||||||
*/
|
*/
|
||||||
|
// Package visible for use by nested classes.
|
||||||
transient int modCount;
|
transient int modCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of this Hashtable: denotes the number of key-value pairs.
|
* The size of this Hashtable: denotes the number of key-value pairs.
|
||||||
*/
|
*/
|
||||||
|
// Package visible for use by nested classes.
|
||||||
transient int size;
|
transient int size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache for {@link #keySet()}.
|
||||||
|
*/
|
||||||
|
private transient Set keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache for {@link #values()}.
|
||||||
|
*/
|
||||||
|
private transient Collection values;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cache for {@link #entrySet()}.
|
||||||
|
*/
|
||||||
|
private transient Set entries;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to represent an entry in the hash table. Holds a single key-value
|
* Class to represent an entry in the hash table. Holds a single key-value
|
||||||
* pair. A Hashtable Entry is identical to a HashMap Entry, except that
|
* pair. A Hashtable Entry is identical to a HashMap Entry, except that
|
||||||
* `null' is not allowed for keys and values.
|
* `null' is not allowed for keys and values.
|
||||||
*/
|
*/
|
||||||
static class HashEntry extends BasicMapEntry
|
private static final class HashEntry extends BasicMapEntry
|
||||||
{
|
{
|
||||||
/** The next entry in the linked list. */
|
/** The next entry in the linked list. */
|
||||||
HashEntry next;
|
HashEntry next;
|
||||||
|
@ -159,7 +186,7 @@ public class Hashtable extends Dictionary
|
||||||
* @return the prior value
|
* @return the prior value
|
||||||
* @throws NullPointerException if <code>newVal</code> is null
|
* @throws NullPointerException if <code>newVal</code> is null
|
||||||
*/
|
*/
|
||||||
public final Object setValue(Object newVal)
|
public Object setValue(Object newVal)
|
||||||
{
|
{
|
||||||
if (newVal == null)
|
if (newVal == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
@ -193,15 +220,15 @@ public class Hashtable extends Dictionary
|
||||||
public Hashtable(Map m)
|
public Hashtable(Map m)
|
||||||
{
|
{
|
||||||
this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
|
this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
|
||||||
putAll(m);
|
putAllInternal(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new Hashtable with a specific inital capacity and
|
* Construct a new Hashtable with a specific inital capacity and
|
||||||
* default load factor of 0.75.
|
* default load factor of 0.75.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity of this Hashtable (>=0)
|
* @param initialCapacity the initial capacity of this Hashtable (>= 0)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0)
|
* @throws IllegalArgumentException if (initialCapacity < 0)
|
||||||
*/
|
*/
|
||||||
public Hashtable(int initialCapacity)
|
public Hashtable(int initialCapacity)
|
||||||
{
|
{
|
||||||
|
@ -212,10 +239,10 @@ public class Hashtable extends Dictionary
|
||||||
* Construct a new Hashtable with a specific initial capacity and
|
* Construct a new Hashtable with a specific initial capacity and
|
||||||
* load factor.
|
* load factor.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity (>=0)
|
* @param initialCapacity the initial capacity (>= 0)
|
||||||
* @param loadFactor the load factor (>0, not NaN)
|
* @param loadFactor the load factor (> 0, not NaN)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||||
* ! (loadFactor > 0.0)
|
* ! (loadFactor > 0.0)
|
||||||
*/
|
*/
|
||||||
public Hashtable(int initialCapacity, float loadFactor)
|
public Hashtable(int initialCapacity, float loadFactor)
|
||||||
{
|
{
|
||||||
|
@ -251,30 +278,36 @@ public class Hashtable extends Dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an enumeration of the keys of this table.
|
* Return an enumeration of the keys of this table. There's no point
|
||||||
|
* in synchronizing this, as you have already been warned that the
|
||||||
|
* enumeration is not specified to be thread-safe.
|
||||||
|
*
|
||||||
* @return the keys
|
* @return the keys
|
||||||
* @see #elements()
|
* @see #elements()
|
||||||
* @see #keySet()
|
* @see #keySet()
|
||||||
*/
|
*/
|
||||||
public synchronized Enumeration keys()
|
public Enumeration keys()
|
||||||
{
|
{
|
||||||
return new Enumerator(Enumerator.KEYS);
|
return new Enumerator(KEYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an enumeration of the values of this table.
|
* Return an enumeration of the values of this table. There's no point
|
||||||
|
* in synchronizing this, as you have already been warned that the
|
||||||
|
* enumeration is not specified to be thread-safe.
|
||||||
|
*
|
||||||
* @return the values
|
* @return the values
|
||||||
* @see #keys()
|
* @see #keys()
|
||||||
* @see #values()
|
* @see #values()
|
||||||
*/
|
*/
|
||||||
public synchronized Enumeration elements()
|
public Enumeration elements()
|
||||||
{
|
{
|
||||||
return new Enumerator(Enumerator.VALUES);
|
return new Enumerator(VALUES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Hashtable contains a value <pre>o</pre>,
|
* Returns true if this Hashtable contains a value <code>o</code>,
|
||||||
* such that <pre>o.equals(value)</pre>. This is the same as
|
* such that <code>o.equals(value)</code>. This is the same as
|
||||||
* <code>containsValue()</code>, and is O(n).
|
* <code>containsValue()</code>, and is O(n).
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
|
@ -284,22 +317,37 @@ public class Hashtable extends Dictionary
|
||||||
*
|
*
|
||||||
* @param value the value to search for in this Hashtable
|
* @param value the value to search for in this Hashtable
|
||||||
* @return true if at least one key maps to the value
|
* @return true if at least one key maps to the value
|
||||||
* @throws NullPointerException if <pre>value</pre> is null
|
* @throws NullPointerException if <code>value</code> is null
|
||||||
* @see #containsValue(Object)
|
* @see #containsValue(Object)
|
||||||
* @see #containsKey(Object)
|
* @see #containsKey(Object)
|
||||||
*/
|
*/
|
||||||
public synchronized boolean contains(Object value)
|
public synchronized boolean contains(Object value)
|
||||||
{
|
{
|
||||||
// Check if value is null in case Hashtable is empty.
|
// Check if value is null.
|
||||||
if (value == null)
|
if (value == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
return containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this Hashtable contains a value <code>o</code>, such that
|
||||||
|
* <code>o.equals(value)</code>. This is the new API for the old
|
||||||
|
* <code>contains()</code>, except that it is forgiving of null.
|
||||||
|
*
|
||||||
|
* @param value the value to search for in this Hashtable
|
||||||
|
* @return true if at least one key maps to the value
|
||||||
|
* @see #contains(Object)
|
||||||
|
* @see #containsKey(Object)
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
public boolean containsValue(Object value)
|
||||||
|
{
|
||||||
for (int i = buckets.length - 1; i >= 0; i--)
|
for (int i = buckets.length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
HashEntry e = buckets[i];
|
HashEntry e = buckets[i];
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (value.equals(e.value))
|
if (AbstractCollection.equals(value, e.value))
|
||||||
return true;
|
return true;
|
||||||
e = e.next;
|
e = e.next;
|
||||||
}
|
}
|
||||||
|
@ -308,24 +356,7 @@ public class Hashtable extends Dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Hashtable contains a value <pre>o</pre>, such that
|
* Returns true if the supplied object <code>equals()</code> a key
|
||||||
* <pre>o.equals(value)</pre>. This is the new API for the old
|
|
||||||
* <code>contains()</code>.
|
|
||||||
*
|
|
||||||
* @param value the value to search for in this Hashtable
|
|
||||||
* @return true if at least one key maps to the value
|
|
||||||
* @throws NullPointerException if <pre>value</pre> is null
|
|
||||||
* @see #contains(Object)
|
|
||||||
* @see #containsKey(Object)
|
|
||||||
* @since 1.2
|
|
||||||
*/
|
|
||||||
public boolean containsValue(Object value)
|
|
||||||
{
|
|
||||||
return contains(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the supplied object <pre>equals()</pre> a key
|
|
||||||
* in this Hashtable.
|
* in this Hashtable.
|
||||||
*
|
*
|
||||||
* @param key the key to search for in this Hashtable
|
* @param key the key to search for in this Hashtable
|
||||||
|
@ -348,7 +379,7 @@ public class Hashtable extends Dictionary
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value in this Hashtable associated with the supplied key,
|
* Return the value in this Hashtable associated with the supplied key,
|
||||||
* or <pre>null</pre> if the key maps to nothing.
|
* or <code>null</code> if the key maps to nothing.
|
||||||
*
|
*
|
||||||
* @param key the key for which to fetch an associated value
|
* @param key the key for which to fetch an associated value
|
||||||
* @return what the key maps to, if present
|
* @return what the key maps to, if present
|
||||||
|
@ -383,7 +414,6 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public synchronized Object put(Object key, Object value)
|
public synchronized Object put(Object key, Object value)
|
||||||
{
|
{
|
||||||
modCount++;
|
|
||||||
int idx = hash(key);
|
int idx = hash(key);
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
|
|
||||||
|
@ -407,6 +437,7 @@ public class Hashtable extends Dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point, we know we need to add a new entry.
|
// At this point, we know we need to add a new entry.
|
||||||
|
modCount++;
|
||||||
if (++size > threshold)
|
if (++size > threshold)
|
||||||
{
|
{
|
||||||
rehash();
|
rehash();
|
||||||
|
@ -425,15 +456,18 @@ public class Hashtable extends Dictionary
|
||||||
/**
|
/**
|
||||||
* Removes from the table and returns the value which is mapped by the
|
* Removes from the table and returns the value which is mapped by the
|
||||||
* supplied key. If the key maps to nothing, then the table remains
|
* supplied key. If the key maps to nothing, then the table remains
|
||||||
* unchanged, and <pre>null</pre> is returned.
|
* unchanged, and <code>null</code> is returned.
|
||||||
|
* <b>NOTE:</b>Map.remove and Dictionary.remove disagree whether null
|
||||||
|
* is a valid parameter; at the moment, this implementation obeys Map.remove,
|
||||||
|
* and silently ignores null.
|
||||||
*
|
*
|
||||||
* @param key the key used to locate the value to remove
|
* @param key the key used to locate the value to remove
|
||||||
* @return whatever the key mapped to, if present
|
* @return whatever the key mapped to, if present
|
||||||
* @throws NullPointerException if key is null
|
|
||||||
*/
|
*/
|
||||||
public synchronized Object remove(Object key)
|
public synchronized Object remove(Object key)
|
||||||
{
|
{
|
||||||
modCount++;
|
if (key == null)
|
||||||
|
return null;
|
||||||
int idx = hash(key);
|
int idx = hash(key);
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
HashEntry last = null;
|
HashEntry last = null;
|
||||||
|
@ -442,6 +476,7 @@ public class Hashtable extends Dictionary
|
||||||
{
|
{
|
||||||
if (key.equals(e.key))
|
if (key.equals(e.key))
|
||||||
{
|
{
|
||||||
|
modCount++;
|
||||||
if (last == null)
|
if (last == null)
|
||||||
buckets[idx] = e.next;
|
buckets[idx] = e.next;
|
||||||
else
|
else
|
||||||
|
@ -488,9 +523,12 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public synchronized void clear()
|
public synchronized void clear()
|
||||||
{
|
{
|
||||||
modCount++;
|
if (size > 0)
|
||||||
Arrays.fill(buckets, null);
|
{
|
||||||
size = 0;
|
modCount++;
|
||||||
|
Arrays.fill(buckets, null);
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -511,36 +549,18 @@ public class Hashtable extends Dictionary
|
||||||
// This is impossible.
|
// This is impossible.
|
||||||
}
|
}
|
||||||
copy.buckets = new HashEntry[buckets.length];
|
copy.buckets = new HashEntry[buckets.length];
|
||||||
|
copy.putAllInternal(this);
|
||||||
for (int i = buckets.length - 1; i >= 0; i--)
|
// Clear the caches.
|
||||||
{
|
copy.keys = null;
|
||||||
HashEntry e = buckets[i];
|
copy.values = null;
|
||||||
HashEntry last = null;
|
copy.entries = null;
|
||||||
|
|
||||||
while (e != null)
|
|
||||||
{
|
|
||||||
if (last == null)
|
|
||||||
{
|
|
||||||
last = new HashEntry(e.key, e.value);
|
|
||||||
copy.buckets[i] = last;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last.next = new HashEntry(e.key, e.value);
|
|
||||||
last = last.next;
|
|
||||||
}
|
|
||||||
e = e.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this Hashtable to a String, surrounded by braces (<pre>'{'</pre>
|
* Converts this Hashtable to a String, surrounded by braces, and with
|
||||||
* and <pre>'}'</pre>), key/value pairs listed with an equals sign between,
|
* key/value pairs listed with an equals sign between, separated by a
|
||||||
* (<pre>'='</pre>), and pairs separated by comma and space
|
* comma and space. For example, <code>"{a=1, b=2}"</code>.<p>
|
||||||
* (<pre>", "</pre>).
|
|
||||||
* <p>
|
|
||||||
*
|
*
|
||||||
* NOTE: if the <code>toString()</code> method of any key or value
|
* NOTE: if the <code>toString()</code> method of any key or value
|
||||||
* throws an exception, this will fail for the same reason.
|
* throws an exception, this will fail for the same reason.
|
||||||
|
@ -552,7 +572,7 @@ public class Hashtable extends Dictionary
|
||||||
// Since we are already synchronized, and entrySet().iterator()
|
// Since we are already synchronized, and entrySet().iterator()
|
||||||
// would repeatedly re-lock/release the monitor, we directly use the
|
// would repeatedly re-lock/release the monitor, we directly use the
|
||||||
// unsynchronized HashIterator instead.
|
// unsynchronized HashIterator instead.
|
||||||
Iterator entries = new HashIterator(HashIterator.ENTRIES);
|
Iterator entries = new HashIterator(ENTRIES);
|
||||||
StringBuffer r = new StringBuffer("{");
|
StringBuffer r = new StringBuffer("{");
|
||||||
for (int pos = size; pos > 0; pos--)
|
for (int pos = size; pos > 0; pos--)
|
||||||
{
|
{
|
||||||
|
@ -568,9 +588,11 @@ public class Hashtable extends Dictionary
|
||||||
* Returns a "set view" of this Hashtable's keys. The set is backed by
|
* Returns a "set view" of this Hashtable's keys. The set is backed by
|
||||||
* the hashtable, so changes in one show up in the other. The set supports
|
* the hashtable, so changes in one show up in the other. The set supports
|
||||||
* element removal, but not element addition. The set is properly
|
* element removal, but not element addition. The set is properly
|
||||||
* synchronized on the original hashtable. The set will throw a
|
* synchronized on the original hashtable. Sun has not documented the
|
||||||
* {@link NullPointerException} if null is passed to <code>contains</code>,
|
* proper interaction of null with this set, but has inconsistent behavior
|
||||||
* <code>remove</code>, or related methods.
|
* in the JDK. Therefore, in this implementation, contains, remove,
|
||||||
|
* containsAll, retainAll, removeAll, and equals just ignore a null key
|
||||||
|
* rather than throwing a {@link NullPointerException}.
|
||||||
*
|
*
|
||||||
* @return a set view of the keys
|
* @return a set view of the keys
|
||||||
* @see #values()
|
* @see #values()
|
||||||
|
@ -579,50 +601,56 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public Set keySet()
|
public Set keySet()
|
||||||
{
|
{
|
||||||
// Create a synchronized AbstractSet with custom implementations of those
|
if (keys == null)
|
||||||
// methods that can be overridden easily and efficiently.
|
|
||||||
Set r = new AbstractSet()
|
|
||||||
{
|
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
// Create a synchronized AbstractSet with custom implementations of
|
||||||
}
|
// those methods that can be overridden easily and efficiently.
|
||||||
|
Set r = new AbstractSet()
|
||||||
|
{
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return new HashIterator(HashIterator.KEYS);
|
return new HashIterator(KEYS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
Hashtable.this.clear();
|
Hashtable.this.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(Object o)
|
public boolean contains(Object o)
|
||||||
{
|
{
|
||||||
return Hashtable.this.containsKey(o);
|
if (o == null)
|
||||||
}
|
return false;
|
||||||
|
return containsKey(o);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean remove(Object o)
|
public boolean remove(Object o)
|
||||||
{
|
{
|
||||||
return (Hashtable.this.remove(o) != null);
|
return Hashtable.this.remove(o) != null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We must specify the correct object to synchronize upon, hence the
|
||||||
|
// use of a non-public API
|
||||||
|
keys = new Collections.SynchronizedSet(this, r);
|
||||||
}
|
}
|
||||||
};
|
return keys;
|
||||||
|
|
||||||
// We must specify the correct object to synchronize upon, hence the
|
|
||||||
// use of a non-public API
|
|
||||||
return new Collections.SynchronizedSet(this, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a "collection view" (or "bag view") of this Hashtable's values.
|
* Returns a "collection view" (or "bag view") of this Hashtable's values.
|
||||||
* The collection is backed by the hashtable, so changes in one show up
|
* The collection is backed by the hashtable, so changes in one show up
|
||||||
* in the other. The collection supports element removal, but not element
|
* in the other. The collection supports element removal, but not element
|
||||||
* addition. The collection is properly synchronized on the original
|
* addition. The collection is properly synchronized on the original
|
||||||
* hashtable. The collection will throw a {@link NullPointerException}
|
* hashtable. Sun has not documented the proper interaction of null with
|
||||||
* if null is passed to <code>contains</code> or related methods, but not
|
* this set, but has inconsistent behavior in the JDK. Therefore, in this
|
||||||
* if passed to <code>remove</code> or related methods.
|
* implementation, contains, remove, containsAll, retainAll, removeAll, and
|
||||||
|
* equals just ignore a null value rather than throwing a
|
||||||
|
* {@link NullPointerException}.
|
||||||
*
|
*
|
||||||
* @return a bag view of the values
|
* @return a bag view of the values
|
||||||
* @see #keySet()
|
* @see #keySet()
|
||||||
|
@ -631,46 +659,45 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public Collection values()
|
public Collection values()
|
||||||
{
|
{
|
||||||
// We don't bother overriding many of the optional methods, as doing so
|
if (values == null)
|
||||||
// wouldn't provide any significant performance advantage.
|
|
||||||
Collection r = new AbstractCollection()
|
|
||||||
{
|
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
// We don't bother overriding many of the optional methods, as doing so
|
||||||
}
|
// wouldn't provide any significant performance advantage.
|
||||||
|
Collection r = new AbstractCollection()
|
||||||
|
{
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
public Iterator iterator()
|
public Iterator iterator()
|
||||||
{
|
{
|
||||||
return new HashIterator(HashIterator.VALUES);
|
return new HashIterator(VALUES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear()
|
public void clear()
|
||||||
{
|
{
|
||||||
Hashtable.this.clear();
|
Hashtable.this.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We must specify the correct object to synchronize upon, hence the
|
||||||
|
// use of a non-public API
|
||||||
|
values = new Collections.SynchronizedCollection(this, r);
|
||||||
}
|
}
|
||||||
|
return values;
|
||||||
// Override this so that we check for null
|
|
||||||
public boolean contains(Object o)
|
|
||||||
{
|
|
||||||
return Hashtable.this.contains(o);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We must specify the correct object to synchronize upon, hence the
|
|
||||||
// use of a non-public API
|
|
||||||
return new Collections.SynchronizedCollection(this, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a "set view" of this Hashtable's entries. The set is backed by
|
* Returns a "set view" of this Hashtable's entries. The set is backed by
|
||||||
* the hashtable, so changes in one show up in the other. The set supports
|
* the hashtable, so changes in one show up in the other. The set supports
|
||||||
* element removal, but not element addition. The set is properly
|
* element removal, but not element addition. The set is properly
|
||||||
* synchronized on the original hashtable. The set will throw a
|
* synchronized on the original hashtable. Sun has not documented the
|
||||||
* {@link NullPointerException} if the Map.Entry passed to
|
* proper interaction of null with this set, but has inconsistent behavior
|
||||||
* <code>contains</code>, <code>remove</code>, or related methods returns
|
* in the JDK. Therefore, in this implementation, contains, remove,
|
||||||
* null for <code>getKey</code>, but not if the Map.Entry is null or
|
* containsAll, retainAll, removeAll, and equals just ignore a null entry,
|
||||||
* returns null for <code>getValue</code>.
|
* or an entry with a null key or value, rather than throwing a
|
||||||
|
* {@link NullPointerException}. However, calling entry.setValue(null)
|
||||||
|
* will fail.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* Note that the iterators for all three views, from keySet(), entrySet(),
|
* Note that the iterators for all three views, from keySet(), entrySet(),
|
||||||
|
@ -684,49 +711,52 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public Set entrySet()
|
public Set entrySet()
|
||||||
{
|
{
|
||||||
// Create an AbstractSet with custom implementations of those methods that
|
if (entries == null)
|
||||||
// can be overridden easily and efficiently.
|
|
||||||
Set r = new AbstractSet()
|
|
||||||
{
|
|
||||||
public int size()
|
|
||||||
{
|
{
|
||||||
return size;
|
// Create an AbstractSet with custom implementations of those methods
|
||||||
}
|
// that can be overridden easily and efficiently.
|
||||||
|
Set r = new AbstractSet()
|
||||||
public Iterator iterator()
|
{
|
||||||
{
|
public int size()
|
||||||
return new HashIterator(HashIterator.ENTRIES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear()
|
|
||||||
{
|
|
||||||
Hashtable.this.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Object o)
|
|
||||||
{
|
|
||||||
return getEntry(o) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(Object o)
|
|
||||||
{
|
|
||||||
HashEntry e = getEntry(o);
|
|
||||||
if (e != null)
|
|
||||||
{
|
{
|
||||||
Hashtable.this.remove(e.key);
|
return size;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We must specify the correct object to synchronize upon, hence the
|
public Iterator iterator()
|
||||||
// use of a non-public API
|
{
|
||||||
return new Collections.SynchronizedSet(this, r);
|
return new HashIterator(ENTRIES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
Hashtable.this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object o)
|
||||||
|
{
|
||||||
|
return getEntry(o) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object o)
|
||||||
|
{
|
||||||
|
HashEntry e = getEntry(o);
|
||||||
|
if (e != null)
|
||||||
|
{
|
||||||
|
Hashtable.this.remove(e.key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// We must specify the correct object to synchronize upon, hence the
|
||||||
|
// use of a non-public API
|
||||||
|
entries = new Collections.SynchronizedSet(this, r);
|
||||||
|
}
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Hashtable equals the supplied Object <pre>o</pre>.
|
* Returns true if this Hashtable equals the supplied Object <code>o</code>.
|
||||||
* As specified by Map, this is:
|
* As specified by Map, this is:
|
||||||
* <pre>
|
* <pre>
|
||||||
* (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
|
* (o instanceof Map) && entrySet().equals(((Map) o).entrySet());
|
||||||
|
@ -759,7 +789,7 @@ public class Hashtable extends Dictionary
|
||||||
// Since we are already synchronized, and entrySet().iterator()
|
// Since we are already synchronized, and entrySet().iterator()
|
||||||
// would repeatedly re-lock/release the monitor, we directly use the
|
// would repeatedly re-lock/release the monitor, we directly use the
|
||||||
// unsynchronized HashIterator instead.
|
// unsynchronized HashIterator instead.
|
||||||
Iterator itr = new HashIterator(HashIterator.ENTRIES);
|
Iterator itr = new HashIterator(ENTRIES);
|
||||||
int hashcode = 0;
|
int hashcode = 0;
|
||||||
for (int pos = size; pos > 0; pos--)
|
for (int pos = size; pos > 0; pos--)
|
||||||
hashcode += itr.next().hashCode();
|
hashcode += itr.next().hashCode();
|
||||||
|
@ -782,29 +812,55 @@ public class Hashtable extends Dictionary
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method for entrySet(), which matches both key and value
|
* Helper method for entrySet(), which matches both key and value
|
||||||
* simultaneously.
|
* simultaneously. Ignores null, as mentioned in entrySet().
|
||||||
*
|
*
|
||||||
* @param o the entry to match
|
* @param o the entry to match
|
||||||
* @return the matching entry, if found, or null
|
* @return the matching entry, if found, or null
|
||||||
* @throws NullPointerException if me.getKey() returns null
|
|
||||||
* @see #entrySet()
|
* @see #entrySet()
|
||||||
*/
|
*/
|
||||||
private HashEntry getEntry(Object o)
|
private HashEntry getEntry(Object o)
|
||||||
{
|
{
|
||||||
if (!(o instanceof Map.Entry))
|
if (! (o instanceof Map.Entry))
|
||||||
return null;
|
return null;
|
||||||
Map.Entry me = (Map.Entry) o;
|
Object key = ((Map.Entry) o).getKey();
|
||||||
int idx = hash(me.getKey());
|
if (key == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int idx = hash(key);
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (e.equals(me))
|
if (o.equals(e))
|
||||||
return e;
|
return e;
|
||||||
e = e.next;
|
e = e.next;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simplified, more efficient internal implementation of putAll(). The
|
||||||
|
* Map constructor and clone() should not call putAll or put, in order to
|
||||||
|
* be compatible with the JDK implementation with respect to subclasses.
|
||||||
|
*
|
||||||
|
* @param m the map to initialize this from
|
||||||
|
*/
|
||||||
|
void putAllInternal(Map m)
|
||||||
|
{
|
||||||
|
Iterator itr = m.entrySet().iterator();
|
||||||
|
int msize = m.size();
|
||||||
|
this.size = msize;
|
||||||
|
|
||||||
|
for (; msize > 0; msize--)
|
||||||
|
{
|
||||||
|
Map.Entry e = (Map.Entry) itr.next();
|
||||||
|
Object key = e.getKey();
|
||||||
|
int idx = hash(key);
|
||||||
|
HashEntry he = new HashEntry(key, e.getValue());
|
||||||
|
he.next = buckets[idx];
|
||||||
|
buckets[idx] = he;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the size of the Hashtable and rehashes all keys to new array
|
* Increases the size of the Hashtable and rehashes all keys to new array
|
||||||
* indices; this is called when the addition of a new value would cause
|
* indices; this is called when the addition of a new value would cause
|
||||||
|
@ -813,7 +869,8 @@ public class Hashtable extends Dictionary
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* This is not specified, but the new size is twice the current size plus
|
* This is not specified, but the new size is twice the current size plus
|
||||||
* one; this number is not always prime, unfortunately.
|
* one; this number is not always prime, unfortunately. This implementation
|
||||||
|
* is not synchronized, as it is only invoked from synchronized methods.
|
||||||
*/
|
*/
|
||||||
protected void rehash()
|
protected void rehash()
|
||||||
{
|
{
|
||||||
|
@ -854,8 +911,8 @@ public class Hashtable extends Dictionary
|
||||||
*
|
*
|
||||||
* @param s the stream to write to
|
* @param s the stream to write to
|
||||||
* @throws IOException if the underlying stream fails
|
* @throws IOException if the underlying stream fails
|
||||||
* @serialData the <i>capacity</i>(int) that is the length of the
|
* @serialData the <i>capacity</i> (int) that is the length of the
|
||||||
* bucket array, the <i>size</i>(int) of the hash map
|
* bucket array, the <i>size</i> (int) of the hash map
|
||||||
* are emitted first. They are followed by size entries,
|
* are emitted first. They are followed by size entries,
|
||||||
* each consisting of a key (Object) and a value (Object).
|
* each consisting of a key (Object) and a value (Object).
|
||||||
*/
|
*/
|
||||||
|
@ -870,7 +927,7 @@ public class Hashtable extends Dictionary
|
||||||
// Since we are already synchronized, and entrySet().iterator()
|
// Since we are already synchronized, and entrySet().iterator()
|
||||||
// would repeatedly re-lock/release the monitor, we directly use the
|
// would repeatedly re-lock/release the monitor, we directly use the
|
||||||
// unsynchronized HashIterator instead.
|
// unsynchronized HashIterator instead.
|
||||||
Iterator it = new HashIterator(HashIterator.ENTRIES);
|
Iterator it = new HashIterator(ENTRIES);
|
||||||
while (it.hasNext())
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
HashEntry entry = (HashEntry) it.next();
|
HashEntry entry = (HashEntry) it.next();
|
||||||
|
@ -885,8 +942,8 @@ public class Hashtable extends Dictionary
|
||||||
* @param s the stream to read from
|
* @param s the stream to read from
|
||||||
* @throws ClassNotFoundException if the underlying stream fails
|
* @throws ClassNotFoundException if the underlying stream fails
|
||||||
* @throws IOException if the underlying stream fails
|
* @throws IOException if the underlying stream fails
|
||||||
* @serialData the <i>capacity</i>(int) that is the length of the
|
* @serialData the <i>capacity</i> (int) that is the length of the
|
||||||
* bucket array, the <i>size</i>(int) of the hash map
|
* bucket array, the <i>size</i> (int) of the hash map
|
||||||
* are emitted first. They are followed by size entries,
|
* are emitted first. They are followed by size entries,
|
||||||
* each consisting of a key (Object) and a value (Object).
|
* each consisting of a key (Object) and a value (Object).
|
||||||
*/
|
*/
|
||||||
|
@ -901,7 +958,8 @@ public class Hashtable extends Dictionary
|
||||||
int len = s.readInt();
|
int len = s.readInt();
|
||||||
|
|
||||||
// Read and use key/value pairs.
|
// Read and use key/value pairs.
|
||||||
for ( ; len > 0; len--)
|
// TODO: should we be defensive programmers, and check for illegal nulls?
|
||||||
|
while (--len >= 0)
|
||||||
put(s.readObject(), s.readObject());
|
put(s.readObject(), s.readObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,13 +974,8 @@ public class Hashtable extends Dictionary
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
*/
|
*/
|
||||||
class HashIterator implements Iterator
|
private final class HashIterator implements Iterator
|
||||||
{
|
{
|
||||||
/** "enum" of iterator types. */
|
|
||||||
static final int KEYS = 0,
|
|
||||||
VALUES = 1,
|
|
||||||
ENTRIES = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
|
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
|
||||||
* or {@link #ENTRIES}.
|
* or {@link #ENTRIES}.
|
||||||
|
@ -988,14 +1041,14 @@ public class Hashtable extends Dictionary
|
||||||
last = e;
|
last = e;
|
||||||
if (type == VALUES)
|
if (type == VALUES)
|
||||||
return e.value;
|
return e.value;
|
||||||
else if (type == KEYS)
|
if (type == KEYS)
|
||||||
return e.key;
|
return e.key;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes from the backing Hashtable the last element which was fetched
|
* Removes from the backing Hashtable the last element which was fetched
|
||||||
* with the <pre>next()</pre> method.
|
* with the <code>next()</code> method.
|
||||||
* @throws ConcurrentModificationException if the hashtable was modified
|
* @throws ConcurrentModificationException if the hashtable was modified
|
||||||
* @throws IllegalStateException if called when there is no last element
|
* @throws IllegalStateException if called when there is no last element
|
||||||
*/
|
*/
|
||||||
|
@ -1007,10 +1060,10 @@ public class Hashtable extends Dictionary
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
Hashtable.this.remove(last.key);
|
Hashtable.this.remove(last.key);
|
||||||
knownMod++;
|
|
||||||
last = null;
|
last = null;
|
||||||
|
knownMod++;
|
||||||
}
|
}
|
||||||
}
|
} // class HashIterator
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1027,21 +1080,21 @@ public class Hashtable extends Dictionary
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
*/
|
*/
|
||||||
class Enumerator implements Enumeration
|
private final class Enumerator implements Enumeration
|
||||||
{
|
{
|
||||||
/** "enum" of iterator types. */
|
|
||||||
static final int KEYS = 0,
|
|
||||||
VALUES = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of this Iterator: {@link #KEYS} or {@link #VALUES}.
|
* The type of this Iterator: {@link #KEYS} or {@link #VALUES}.
|
||||||
*/
|
*/
|
||||||
int type;
|
final int type;
|
||||||
|
/** The number of elements remaining to be returned by next(). */
|
||||||
|
int count = size;
|
||||||
/** Current index in the physical hash table. */
|
/** Current index in the physical hash table. */
|
||||||
int idx;
|
int idx = buckets.length;
|
||||||
/** The last Entry returned by nextEntry(). */
|
/**
|
||||||
HashEntry last;
|
* Entry which will be returned by the next nextElement() call. It is
|
||||||
/** Entry which will be returned by the next nextElement() call. */
|
* set if we are iterating through a bucket with multiple entries, or null
|
||||||
|
* if we must look in the next bucket.
|
||||||
|
*/
|
||||||
HashEntry next;
|
HashEntry next;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1051,25 +1104,6 @@ public class Hashtable extends Dictionary
|
||||||
Enumerator(int type)
|
Enumerator(int type)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.idx = buckets.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to find the next entry.
|
|
||||||
* @return the next entry, or null
|
|
||||||
*/
|
|
||||||
private HashEntry nextEntry()
|
|
||||||
{
|
|
||||||
HashEntry e = null;
|
|
||||||
|
|
||||||
if (last != null)
|
|
||||||
e = last.next;
|
|
||||||
|
|
||||||
while (e == null && idx > 0)
|
|
||||||
e = buckets[--idx];
|
|
||||||
|
|
||||||
last = e;
|
|
||||||
return e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1078,10 +1112,7 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public boolean hasMoreElements()
|
public boolean hasMoreElements()
|
||||||
{
|
{
|
||||||
if (next != null)
|
return count > 0;
|
||||||
return true;
|
|
||||||
next = nextEntry();
|
|
||||||
return next != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1091,19 +1122,16 @@ public class Hashtable extends Dictionary
|
||||||
*/
|
*/
|
||||||
public Object nextElement()
|
public Object nextElement()
|
||||||
{
|
{
|
||||||
HashEntry e;
|
if (count == 0)
|
||||||
if (next != null)
|
|
||||||
{
|
|
||||||
e = next;
|
|
||||||
next = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
e = nextEntry();
|
|
||||||
if (e == null)
|
|
||||||
throw new NoSuchElementException("Hashtable Enumerator");
|
throw new NoSuchElementException("Hashtable Enumerator");
|
||||||
if (type == VALUES)
|
count--;
|
||||||
return e.value;
|
HashEntry e = next;
|
||||||
return e.key;
|
|
||||||
|
while (e == null)
|
||||||
|
e = buckets[--idx];
|
||||||
|
|
||||||
|
next = e.next;
|
||||||
|
return type == VALUES ? e.value : e.key;
|
||||||
}
|
}
|
||||||
}
|
} // class Enumerator
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,11 +28,6 @@ executable file might be covered by the GNU General Public License. */
|
||||||
|
|
||||||
package java.util;
|
package java.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides a hashtable-backed implementation of the
|
* This class provides a hashtable-backed implementation of the
|
||||||
* Map interface, with predictable traversal order.
|
* Map interface, with predictable traversal order.
|
||||||
|
@ -89,6 +84,7 @@ import java.io.ObjectOutputStream;
|
||||||
* @see TreeMap
|
* @see TreeMap
|
||||||
* @see Hashtable
|
* @see Hashtable
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class LinkedHashMap extends HashMap
|
public class LinkedHashMap extends HashMap
|
||||||
{
|
{
|
||||||
|
@ -218,8 +214,8 @@ public class LinkedHashMap extends HashMap
|
||||||
* Construct a new insertion-ordered LinkedHashMap with a specific
|
* Construct a new insertion-ordered LinkedHashMap with a specific
|
||||||
* inital capacity and default load factor of 0.75.
|
* inital capacity and default load factor of 0.75.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity of this HashMap (>=0)
|
* @param initialCapacity the initial capacity of this HashMap (>= 0)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0)
|
* @throws IllegalArgumentException if (initialCapacity < 0)
|
||||||
*/
|
*/
|
||||||
public LinkedHashMap(int initialCapacity)
|
public LinkedHashMap(int initialCapacity)
|
||||||
{
|
{
|
||||||
|
@ -231,10 +227,10 @@ public class LinkedHashMap extends HashMap
|
||||||
* Construct a new insertion-orderd LinkedHashMap with a specific
|
* Construct a new insertion-orderd LinkedHashMap with a specific
|
||||||
* inital capacity and load factor.
|
* inital capacity and load factor.
|
||||||
*
|
*
|
||||||
* @param initialCapacity the initial capacity (>=0)
|
* @param initialCapacity the initial capacity (>= 0)
|
||||||
* @param loadFactor the load factor (>0, not NaN)
|
* @param loadFactor the load factor (> 0, not NaN)
|
||||||
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
* @throws IllegalArgumentException if (initialCapacity < 0) ||
|
||||||
* ! (loadFactor > 0.0)
|
* ! (loadFactor > 0.0)
|
||||||
*/
|
*/
|
||||||
public LinkedHashMap(int initialCapacity, float loadFactor)
|
public LinkedHashMap(int initialCapacity, float loadFactor)
|
||||||
{
|
{
|
||||||
|
@ -281,7 +277,7 @@ public class LinkedHashMap extends HashMap
|
||||||
LinkedHashEntry e = head;
|
LinkedHashEntry e = head;
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (value == null ? e.value == null : value.equals(e.value))
|
if (equals(value, e.value))
|
||||||
return true;
|
return true;
|
||||||
e = e.succ;
|
e = e.succ;
|
||||||
}
|
}
|
||||||
|
@ -307,7 +303,7 @@ public class LinkedHashMap extends HashMap
|
||||||
HashEntry e = buckets[idx];
|
HashEntry e = buckets[idx];
|
||||||
while (e != null)
|
while (e != null)
|
||||||
{
|
{
|
||||||
if (key == null ? e.key == null : key.equals(e.key))
|
if (equals(key, e.key))
|
||||||
{
|
{
|
||||||
if (accessOrder)
|
if (accessOrder)
|
||||||
{
|
{
|
||||||
|
@ -376,13 +372,14 @@ public class LinkedHashMap extends HashMap
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper method called by <code>put</code>, which creates and adds a
|
/**
|
||||||
|
* Helper method called by <code>put</code>, which creates and adds a
|
||||||
* new Entry, followed by performing bookkeeping (like removeEldestEntry).
|
* new Entry, followed by performing bookkeeping (like removeEldestEntry).
|
||||||
*
|
*
|
||||||
* @param key the key of the new Entry
|
* @param key the key of the new Entry
|
||||||
* @param value the value
|
* @param value the value
|
||||||
* @param idx the index in buckets where the new Entry belongs
|
* @param idx the index in buckets where the new Entry belongs
|
||||||
* @param callRemove Whether to call the removeEldestEntry method.
|
* @param callRemove whether to call the removeEldestEntry method
|
||||||
* @see #put(Object, Object)
|
* @see #put(Object, Object)
|
||||||
* @see #removeEldestEntry(Map.Entry)
|
* @see #removeEldestEntry(Map.Entry)
|
||||||
*/
|
*/
|
||||||
|
@ -397,6 +394,11 @@ public class LinkedHashMap extends HashMap
|
||||||
remove(head);
|
remove(head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method, called by clone() to reset the doubly-linked list.
|
||||||
|
* @param m the map to add entries from
|
||||||
|
* @see #clone()
|
||||||
|
*/
|
||||||
void putAllInternal(Map m)
|
void putAllInternal(Map m)
|
||||||
{
|
{
|
||||||
head = null;
|
head = null;
|
||||||
|
@ -466,8 +468,8 @@ public class LinkedHashMap extends HashMap
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
LinkedHashMap.this.remove(last.key);
|
LinkedHashMap.this.remove(last.key);
|
||||||
knownMod++;
|
|
||||||
last = null;
|
last = null;
|
||||||
|
knownMod++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
149
libjava/java/util/LinkedHashSet.java
Normal file
149
libjava/java/util/LinkedHashSet.java
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/* LinkedHashSet.java -- a set backed by a LinkedHashMap, for linked
|
||||||
|
list traversal.
|
||||||
|
Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GNU Classpath.
|
||||||
|
|
||||||
|
GNU Classpath is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GNU Classpath is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GNU Classpath; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA.
|
||||||
|
|
||||||
|
As a special exception, if you link this library with other files to
|
||||||
|
produce an executable, this library does not by itself cause the
|
||||||
|
resulting executable to be covered by the GNU General Public License.
|
||||||
|
This exception does not however invalidate any other reasons why the
|
||||||
|
executable file might be covered by the GNU General Public License. */
|
||||||
|
|
||||||
|
|
||||||
|
package java.util;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides a hashtable-backed implementation of the
|
||||||
|
* Set interface, with predictable traversal order.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* It uses a hash-bucket approach; that is, hash collisions are handled
|
||||||
|
* by linking the new node off of the pre-existing node (or list of
|
||||||
|
* nodes). In this manner, techniques such as linear probing (which
|
||||||
|
* can cause primary clustering) and rehashing (which does not fit very
|
||||||
|
* well with Java's method of precomputing hash codes) are avoided. In
|
||||||
|
* addition, this maintains a doubly-linked list which tracks insertion
|
||||||
|
* order. Note that the insertion order is not modified if an
|
||||||
|
* <code>add</code> simply reinserts an element in the set.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* One of the nice features of tracking insertion order is that you can
|
||||||
|
* copy a set, and regardless of the implementation of the original,
|
||||||
|
* produce the same results when iterating over the copy. This is possible
|
||||||
|
* without needing the overhead of <code>TreeSet</code>.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* Under ideal circumstances (no collisions), LinkedHashSet offers O(1)
|
||||||
|
* performance on most operations. In the worst case (all elements map
|
||||||
|
* to the same hash code -- very unlikely), most operations are O(n).
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* LinkedHashSet accepts the null entry. It is not synchronized, so if
|
||||||
|
* you need multi-threaded access, consider using:<br>
|
||||||
|
* <code>Set s = Collections.synchronizedSet(new LinkedHashSet(...));</code>
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
* modification, except for <code>remove()</code> called on the iterator
|
||||||
|
* itself, cause the iterator to throw a
|
||||||
|
* {@link ConcurrentModificationException} rather than exhibit
|
||||||
|
* non-deterministic behavior.
|
||||||
|
*
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Object#hashCode()
|
||||||
|
* @see Collection
|
||||||
|
* @see Set
|
||||||
|
* @see HashSet
|
||||||
|
* @see TreeSet
|
||||||
|
* @see Collections#synchronizedSet(Set)
|
||||||
|
* @since 1.4
|
||||||
|
* @status updated to 1.4
|
||||||
|
*/
|
||||||
|
public class LinkedHashSet extends HashSet
|
||||||
|
implements Set, Cloneable, Serializable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compatible with JDK 1.4.
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -2851667679971038690L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new, empty HashSet whose backing HashMap has the default
|
||||||
|
* capacity (11) and loadFacor (0.75).
|
||||||
|
*/
|
||||||
|
public LinkedHashSet()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new, empty HashSet whose backing HashMap has the supplied
|
||||||
|
* capacity and the default load factor (0.75).
|
||||||
|
*
|
||||||
|
* @param initialCapacity the initial capacity of the backing HashMap
|
||||||
|
* @throws IllegalArgumentException if the capacity is negative
|
||||||
|
*/
|
||||||
|
public LinkedHashSet(int initialCapacity)
|
||||||
|
{
|
||||||
|
super(initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new, empty HashSet whose backing HashMap has the supplied
|
||||||
|
* capacity and load factor.
|
||||||
|
*
|
||||||
|
* @param initialCapacity the initial capacity of the backing HashMap
|
||||||
|
* @param loadFactor the load factor of the backing HashMap
|
||||||
|
* @throws IllegalArgumentException if either argument is negative, or
|
||||||
|
* if loadFactor is POSITIVE_INFINITY or NaN
|
||||||
|
*/
|
||||||
|
public LinkedHashSet(int initialCapacity, float loadFactor)
|
||||||
|
{
|
||||||
|
super(initialCapacity, loadFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new HashSet with the same elements as are in the supplied
|
||||||
|
* collection (eliminating any duplicates, of course). The backing storage
|
||||||
|
* has twice the size of the collection, or the default size of 11,
|
||||||
|
* whichever is greater; and the default load factor (0.75).
|
||||||
|
*
|
||||||
|
* @param c a collection of initial set elements
|
||||||
|
* @throws NullPointerException if c is null
|
||||||
|
*/
|
||||||
|
public LinkedHashSet(Collection c)
|
||||||
|
{
|
||||||
|
super(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method which initializes the backing Map.
|
||||||
|
*
|
||||||
|
* @param capacity the initial capacity
|
||||||
|
* @param load the initial load factor
|
||||||
|
* @return the backing HashMap
|
||||||
|
*/
|
||||||
|
HashMap init(int capacity, float load)
|
||||||
|
{
|
||||||
|
return new LinkedHashMap(capacity, load);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -190,7 +190,7 @@ public interface List extends Collection
|
||||||
* @see Object#equals(Object)
|
* @see Object#equals(Object)
|
||||||
* @see #hashCode()
|
* @see #hashCode()
|
||||||
*/
|
*/
|
||||||
boolean equals(Object o);
|
/* boolean equals(Object o);*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the element at a given index in this list.
|
* Get the element at a given index in this list.
|
||||||
|
@ -288,7 +288,7 @@ public interface List extends Collection
|
||||||
Object remove(int index);
|
Object remove(int index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the first occurrence of an object from this list (optional
|
* Remove the first occurence of an object from this list (optional
|
||||||
* operation). That is, remove the first element e such that
|
* operation). That is, remove the first element e such that
|
||||||
* <code>o == null ? e == null : o.equals(e)</code>.
|
* <code>o == null ? e == null : o.equals(e)</code>.
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,24 +32,30 @@ package java.util;
|
||||||
* "The Java Language Specification", ISBN 0-201-63451-1
|
* "The Java Language Specification", ISBN 0-201-63451-1
|
||||||
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
|
* plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
|
||||||
* Status: Believed complete and correct
|
* Status: Believed complete and correct
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stack provides a Last In First Out (LIFO) data type, commonly known
|
* Stack provides a Last In First Out (LIFO) data type, commonly known
|
||||||
* as a Stack.
|
* as a Stack. Stack itself extends Vector and provides the additional
|
||||||
*
|
* methods for stack manipulation (push, pop, peek). You can also seek for
|
||||||
* Stack itself extends Vector and provides the additional methods
|
* the 1-based position of an element on the stack.
|
||||||
* for stack manipulation (push, pop, peek).
|
|
||||||
*
|
*
|
||||||
* @author Warren Levy <warrenl@cygnus.com>
|
* @author Warren Levy <warrenl@cygnus.com>
|
||||||
* @date August 20, 1998.
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see List
|
||||||
|
* @see AbstractList
|
||||||
|
* @see LinkedList
|
||||||
|
* @since 1.0
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
public class Stack extends Vector
|
public class Stack extends Vector
|
||||||
{
|
{
|
||||||
// Could use Vector methods internally for the following methods
|
// We could use Vector methods internally for the following methods,
|
||||||
// but have used Vector fields directly for efficiency (i.e. this
|
// but have used Vector fields directly for efficiency (i.e. this
|
||||||
// often reduces out duplicate bounds checking).
|
// often reduces out duplicate bounds checking).
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatible with JDK 1.0+.
|
||||||
|
*/
|
||||||
private static final long serialVersionUID = 1224463164541339165L;
|
private static final long serialVersionUID = 1224463164541339165L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,16 +63,15 @@ public class Stack extends Vector
|
||||||
*/
|
*/
|
||||||
public Stack()
|
public Stack()
|
||||||
{
|
{
|
||||||
super();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes an Object onto the top of the stack. This method is effectively
|
* Pushes an Object onto the top of the stack. This method is effectively
|
||||||
* the same as addElement(item)
|
* the same as addElement(item).
|
||||||
*
|
*
|
||||||
* @param item the Object to push onto the stack
|
* @param item the Object to push onto the stack
|
||||||
* @returns the Object pushed onto the stack
|
* @return the Object pushed onto the stack
|
||||||
* @see java.util.Vector#addElement(java.util.Object)
|
* @see Vector#addElement(Object)
|
||||||
*/
|
*/
|
||||||
public Object push(Object item)
|
public Object push(Object item)
|
||||||
{
|
{
|
||||||
|
@ -80,26 +85,29 @@ public class Stack extends Vector
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pops an item from the stack and returns it. The item popped is
|
* Pops an item from the stack and returns it. The item popped is
|
||||||
* removed from the Stack
|
* removed from the Stack.
|
||||||
*
|
*
|
||||||
* @returns the Object popped from the stack
|
* @return the Object popped from the stack
|
||||||
|
* @throws EmptyStackException if the stack is empty
|
||||||
*/
|
*/
|
||||||
public synchronized Object pop()
|
public synchronized Object pop()
|
||||||
{
|
{
|
||||||
if (elementCount == 0)
|
if (elementCount == 0)
|
||||||
throw new EmptyStackException();
|
throw new EmptyStackException();
|
||||||
|
|
||||||
|
modCount++;
|
||||||
Object obj = elementData[--elementCount];
|
Object obj = elementData[--elementCount];
|
||||||
|
|
||||||
// Set topmost element to null to assist the gc in cleanup
|
// Set topmost element to null to assist the gc in cleanup.
|
||||||
elementData[elementCount] = null;
|
elementData[elementCount] = null;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the top Object on the stack without removing it
|
* Returns the top Object on the stack without removing it.
|
||||||
*
|
*
|
||||||
* @returns the top Object on the stack
|
* @return the top Object on the stack
|
||||||
|
* @throws EmptyStackException if the stack is empty
|
||||||
*/
|
*/
|
||||||
public synchronized Object peek()
|
public synchronized Object peek()
|
||||||
{
|
{
|
||||||
|
@ -110,11 +118,11 @@ public class Stack extends Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if the stack is empty
|
* Tests if the stack is empty.
|
||||||
*
|
*
|
||||||
* @returns true if the stack contains no items, false otherwise
|
* @return true if the stack contains no items, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean empty()
|
public synchronized boolean empty()
|
||||||
{
|
{
|
||||||
return elementCount == 0;
|
return elementCount == 0;
|
||||||
}
|
}
|
||||||
|
@ -122,18 +130,18 @@ public class Stack extends Vector
|
||||||
/**
|
/**
|
||||||
* Returns the position of an Object on the stack, with the top
|
* Returns the position of an Object on the stack, with the top
|
||||||
* most Object being at position 1, and each Object deeper in the
|
* most Object being at position 1, and each Object deeper in the
|
||||||
* stack at depth + 1
|
* stack at depth + 1.
|
||||||
*
|
*
|
||||||
* @param o The object to search for
|
* @param o The object to search for
|
||||||
* @returns The 1 based depth of the Object, or -1 if the Object
|
* @return The 1 based depth of the Object, or -1 if the Object
|
||||||
* is not on the stack.
|
* is not on the stack
|
||||||
*/
|
*/
|
||||||
public synchronized int search(Object o)
|
public synchronized int search(Object o)
|
||||||
{
|
{
|
||||||
for (int i = elementCount-1; i >=0; --i)
|
int i = elementCount;
|
||||||
if (elementData[i].equals(o))
|
while (--i >= 0)
|
||||||
|
if (equals(o, elementData[i]))
|
||||||
return elementCount - i;
|
return elementCount - i;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
/* TreeSet.java -- a class providing a TreeMap-backet SortedSet
|
/* TreeSet.java -- a class providing a TreeMap-backed SortedSet
|
||||||
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of GNU Classpath.
|
This file is part of GNU Classpath.
|
||||||
|
@ -33,54 +33,91 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides a TreeMap-backed implementation of the
|
* This class provides a TreeMap-backed implementation of the SortedSet
|
||||||
* SortedSet interface.
|
* interface. The elements will be sorted according to their <i>natural
|
||||||
|
* order</i>, or according to the provided <code>Comparator</code>.<p>
|
||||||
*
|
*
|
||||||
* Each element in the Set is a key in the backing TreeMap; each key
|
* Most operations are O(log n), but there is so much overhead that this
|
||||||
* maps to a static token, denoting that the key does, in fact, exist.
|
* makes small sets expensive. Note that the ordering must be <i>consistent
|
||||||
|
* with equals</i> to correctly implement the Set interface. If this
|
||||||
|
* condition is violated, the set is still well-behaved, but you may have
|
||||||
|
* suprising results when comparing it to other sets.<p>
|
||||||
*
|
*
|
||||||
* Most operations are O(log n).
|
* This implementation is not synchronized. If you need to share this between
|
||||||
|
* multiple threads, do something like:<br>
|
||||||
|
* <code>SortedSet s
|
||||||
|
* = Collections.synchronizedSortedSet(new TreeSet(...));</code><p>
|
||||||
*
|
*
|
||||||
* TreeSet is a part of the JDK1.2 Collections API.
|
* The iterators are <i>fail-fast</i>, meaning that any structural
|
||||||
|
* modification, except for <code>remove()</code> called on the iterator
|
||||||
|
* itself, cause the iterator to throw a
|
||||||
|
* <code>ConcurrentModificationException</code> rather than exhibit
|
||||||
|
* non-deterministic behavior.
|
||||||
*
|
*
|
||||||
* @author Jon Zeppieri
|
* @author Jon Zeppieri
|
||||||
|
* @author Bryce McKinlay
|
||||||
|
* @author Eric Blake <ebb9@email.byu.edu>
|
||||||
|
* @see Collection
|
||||||
|
* @see Set
|
||||||
|
* @see HashSet
|
||||||
|
* @see LinkedHashSet
|
||||||
|
* @see Comparable
|
||||||
|
* @see Comparator
|
||||||
|
* @see Collections#synchronizedSortedSet(SortedSet)
|
||||||
|
* @see TreeMap
|
||||||
|
* @since 1.2
|
||||||
|
* @status updated to 1.4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TreeSet extends AbstractSet
|
public class TreeSet extends AbstractSet
|
||||||
implements SortedSet, Cloneable, Serializable
|
implements SortedSet, Cloneable, Serializable
|
||||||
{
|
{
|
||||||
/** The TreeMap which backs this Set */
|
/**
|
||||||
transient SortedMap map;
|
* Compatible with JDK 1.2.
|
||||||
|
*/
|
||||||
static final long serialVersionUID = -2479143000061671589L;
|
private static final long serialVersionUID = -2479143000061671589L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new TreeSet whose backing TreeMap using the "natural"
|
* The SortedMap which backs this Set.
|
||||||
* ordering of keys.
|
*/
|
||||||
|
// Not final because of readObject. This will always be one of TreeMap or
|
||||||
|
// TreeMap.SubMap, which both extend AbstractMap.
|
||||||
|
private transient SortedMap map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new TreeSet whose backing TreeMap using the "natural"
|
||||||
|
* ordering of keys. Elements that are not mutually comparable will cause
|
||||||
|
* ClassCastExceptions down the road.
|
||||||
|
*
|
||||||
|
* @see Comparable
|
||||||
*/
|
*/
|
||||||
public TreeSet()
|
public TreeSet()
|
||||||
{
|
{
|
||||||
map = new TreeMap();
|
map = new TreeMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new TreeSet whose backing TreeMap uses the supplied
|
* Construct a new TreeSet whose backing TreeMap uses the supplied
|
||||||
* Comparator.
|
* Comparator. Elements that are not mutually comparable will cause
|
||||||
|
* ClassCastExceptions down the road.
|
||||||
*
|
*
|
||||||
* @param oComparator the Comparator this Set will use
|
* @param comparator the Comparator this Set will use
|
||||||
*/
|
*/
|
||||||
public TreeSet(Comparator comparator)
|
public TreeSet(Comparator comparator)
|
||||||
{
|
{
|
||||||
map = new TreeMap(comparator);
|
map = new TreeMap(comparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new TreeSet whose backing TreeMap uses the "natural"
|
* Construct a new TreeSet whose backing TreeMap uses the "natural"
|
||||||
* orering of the keys and which contains all of the elements in the
|
* orering of the keys and which contains all of the elements in the
|
||||||
* supplied Collection.
|
* supplied Collection. This runs in n*log(n) time.
|
||||||
*
|
*
|
||||||
* @param oCollection the new Set will be initialized with all
|
* @param collection the new Set will be initialized with all
|
||||||
* of the elements in this Collection
|
* of the elements in this Collection
|
||||||
|
* @throws ClassCastException if the elements of the collection are not
|
||||||
|
* comparable
|
||||||
|
* @throws NullPointerException if the collection is null
|
||||||
|
* @see Comparable
|
||||||
*/
|
*/
|
||||||
public TreeSet(Collection collection)
|
public TreeSet(Collection collection)
|
||||||
{
|
{
|
||||||
|
@ -93,54 +130,57 @@ public class TreeSet extends AbstractSet
|
||||||
* SortedSet and containing all of the elements in the supplied SortedSet.
|
* SortedSet and containing all of the elements in the supplied SortedSet.
|
||||||
* This constructor runs in linear time.
|
* This constructor runs in linear time.
|
||||||
*
|
*
|
||||||
* @param sortedSet the new TreeSet will use this SortedSet's
|
* @param sortedSet the new TreeSet will use this SortedSet's comparator
|
||||||
* comparator and will initialize itself
|
* and will initialize itself with all its elements
|
||||||
* with all of the elements in this SortedSet
|
* @throws NullPointerException if sortedSet is null
|
||||||
*/
|
*/
|
||||||
public TreeSet(SortedSet sortedSet)
|
public TreeSet(SortedSet sortedSet)
|
||||||
{
|
{
|
||||||
TreeMap map = new TreeMap(sortedSet.comparator());
|
map = new TreeMap(sortedSet.comparator());
|
||||||
int i = 0;
|
|
||||||
Iterator itr = sortedSet.iterator();
|
Iterator itr = sortedSet.iterator();
|
||||||
map.putKeysLinear(itr, sortedSet.size());
|
((TreeMap) map).putKeysLinear(itr, sortedSet.size());
|
||||||
this.map = map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This private constructor is used to implement the subSet() calls around
|
/**
|
||||||
a backing TreeMap.SubMap. */
|
* This private constructor is used to implement the subSet() calls around
|
||||||
TreeSet(SortedMap backingMap)
|
* a backing TreeMap.SubMap.
|
||||||
|
*
|
||||||
|
* @param backingMap the submap
|
||||||
|
*/
|
||||||
|
private TreeSet(SortedMap backingMap)
|
||||||
{
|
{
|
||||||
map = backingMap;
|
map = backingMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the spplied Object to the Set if it is not already in the Set;
|
* Adds the spplied Object to the Set if it is not already in the Set;
|
||||||
* returns true if the element is added, false otherwise
|
* returns true if the element is added, false otherwise.
|
||||||
*
|
*
|
||||||
* @param obj the Object to be added to this Set
|
* @param obj the Object to be added to this Set
|
||||||
|
* @throws ClassCastException if the element cannot be compared with objects
|
||||||
|
* already in the set
|
||||||
*/
|
*/
|
||||||
public boolean add(Object obj)
|
public boolean add(Object obj)
|
||||||
{
|
{
|
||||||
return (map.put(obj, Boolean.TRUE) == null);
|
return map.put(obj, "") == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds all of the elements in the supplied Collection to this TreeSet.
|
* Adds all of the elements in the supplied Collection to this TreeSet.
|
||||||
*
|
*
|
||||||
* @param c All of the elements in this Collection
|
* @param c The collection to add
|
||||||
* will be added to the Set.
|
* @return true if the Set is altered, false otherwise
|
||||||
*
|
* @throws NullPointerException if c is null
|
||||||
* @return true if the Set is altered, false otherwise
|
* @throws ClassCastException if an element in c cannot be compared with
|
||||||
|
* objects already in the set
|
||||||
*/
|
*/
|
||||||
public boolean addAll(Collection c)
|
public boolean addAll(Collection c)
|
||||||
{
|
{
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
int size = c.size();
|
int pos = c.size();
|
||||||
Iterator itr = c.iterator();
|
Iterator itr = c.iterator();
|
||||||
|
while (--pos >= 0)
|
||||||
for (int i = 0; i < size; i++)
|
result |= (map.put(itr.next(), "") == null);
|
||||||
result |= (map.put(itr.next(), Boolean.TRUE) == null);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,94 +192,75 @@ public class TreeSet extends AbstractSet
|
||||||
map.clear();
|
map.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a shallow copy of this Set. */
|
/**
|
||||||
|
* Returns a shallow copy of this Set. The elements are not cloned.
|
||||||
|
*
|
||||||
|
* @return the cloned set
|
||||||
|
*/
|
||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
TreeSet copy = null;
|
TreeSet copy = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
copy = (TreeSet) super.clone();
|
copy = (TreeSet) super.clone();
|
||||||
|
// Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts.
|
||||||
|
copy.map = (SortedMap) ((AbstractMap) map).clone();
|
||||||
}
|
}
|
||||||
catch (CloneNotSupportedException x)
|
catch (CloneNotSupportedException x)
|
||||||
{
|
{
|
||||||
|
// Impossible result.
|
||||||
}
|
}
|
||||||
copy.map = (SortedMap) ((TreeMap) map).clone();
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns this Set's comparator */
|
/**
|
||||||
|
* Returns this Set's comparator.
|
||||||
|
*
|
||||||
|
* @return the comparator, or null if the set uses natural ordering
|
||||||
|
*/
|
||||||
public Comparator comparator()
|
public Comparator comparator()
|
||||||
{
|
{
|
||||||
return map.comparator();
|
return map.comparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this Set contains the supplied Object,
|
* Returns true if this Set contains the supplied Object, false otherwise.
|
||||||
* false otherwise
|
|
||||||
*
|
*
|
||||||
* @param oObject the Object whose existence in the Set is
|
* @param obj the Object to check for
|
||||||
* being tested
|
* @return true if it is in the set
|
||||||
|
* @throws ClassCastException if obj cannot be compared with objects
|
||||||
|
* already in the set
|
||||||
*/
|
*/
|
||||||
public boolean contains(Object obj)
|
public boolean contains(Object obj)
|
||||||
{
|
{
|
||||||
return map.containsKey(obj);
|
return map.containsKey(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if this Set has size 0, false otherwise */
|
/**
|
||||||
public boolean isEmpty()
|
* Returns the first (by order) element in this Set.
|
||||||
{
|
|
||||||
return map.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the number of elements in this Set */
|
|
||||||
public int size()
|
|
||||||
{
|
|
||||||
return map.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the supplied Object is in this Set, it is removed, and true is
|
|
||||||
* returned; otherwise, false is returned.
|
|
||||||
*
|
*
|
||||||
* @param obj the Object we are attempting to remove
|
* @return the first element
|
||||||
* from this Set
|
* @throws NoSuchElementException if the set is empty
|
||||||
*/
|
*/
|
||||||
public boolean remove(Object obj)
|
|
||||||
{
|
|
||||||
return (map.remove(obj) != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the first (by order) element in this Set */
|
|
||||||
public Object first()
|
public Object first()
|
||||||
{
|
{
|
||||||
return map.firstKey();
|
return map.firstKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the last (by order) element in this Set */
|
|
||||||
public Object last()
|
|
||||||
{
|
|
||||||
return map.lastKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a view of this Set including all elements in the interval
|
* Returns a view of this Set including all elements less than
|
||||||
* [oFromElement, oToElement).
|
* <code>to</code>. The returned set is backed by the original, so changes
|
||||||
|
* in one appear in the other. The subset will throw an
|
||||||
|
* {@link IllegalArgumentException} for any attempt to access or add an
|
||||||
|
* element beyond the specified cutoff. The returned set does not include
|
||||||
|
* the endpoint; if you want inclusion, pass the successor element.
|
||||||
*
|
*
|
||||||
* @param from the resultant view will contain all
|
* @param to the (exclusive) cutoff point
|
||||||
* elements greater than or equal to this element
|
* @return a view of the set less than the cutoff
|
||||||
* @param to the resultant view will contain all
|
* @throws ClassCastException if <code>to</code> is not compatible with
|
||||||
* elements less than this element
|
* the comparator (or is not Comparable, for natural ordering)
|
||||||
*/
|
* @throws NullPointerException if to is null, but the comparator does not
|
||||||
public SortedSet subSet(Object from, Object to)
|
* tolerate null elements
|
||||||
{
|
|
||||||
return new TreeSet(map.subMap(from, to));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a view of this Set including all elements less than oToElement
|
|
||||||
*
|
|
||||||
* @param toElement the resultant view will contain all
|
|
||||||
* elements less than this element
|
|
||||||
*/
|
*/
|
||||||
public SortedSet headSet(Object to)
|
public SortedSet headSet(Object to)
|
||||||
{
|
{
|
||||||
|
@ -247,42 +268,138 @@ public class TreeSet extends AbstractSet
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a view of this Set including all elements greater than or
|
* Returns true if this Set has size 0, false otherwise.
|
||||||
* equal to oFromElement.
|
|
||||||
*
|
*
|
||||||
* @param from the resultant view will contain all
|
* @return true if the set is empty
|
||||||
* elements greater than or equal to this element
|
*/
|
||||||
|
public boolean isEmpty()
|
||||||
|
{
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns in Iterator over the elements in this TreeSet, which traverses
|
||||||
|
* in ascending order.
|
||||||
|
*
|
||||||
|
* @return an iterator
|
||||||
|
*/
|
||||||
|
public Iterator iterator()
|
||||||
|
{
|
||||||
|
return map.keySet().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last (by order) element in this Set.
|
||||||
|
*
|
||||||
|
* @return the last element
|
||||||
|
* @throws NoSuchElementException if the set is empty
|
||||||
|
*/
|
||||||
|
public Object last()
|
||||||
|
{
|
||||||
|
return map.lastKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the supplied Object is in this Set, it is removed, and true is
|
||||||
|
* returned; otherwise, false is returned.
|
||||||
|
*
|
||||||
|
* @param obj the Object to remove from this Set
|
||||||
|
* @return true if the set was modified
|
||||||
|
* @throws ClassCastException if obj cannot be compared to set elements
|
||||||
|
*/
|
||||||
|
public boolean remove(Object obj)
|
||||||
|
{
|
||||||
|
return map.remove(obj) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements in this Set
|
||||||
|
*
|
||||||
|
* @return the set size
|
||||||
|
*/
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a view of this Set including all elements greater or equal to
|
||||||
|
* <code>from</code> and less than <code>to</code> (a half-open interval).
|
||||||
|
* The returned set is backed by the original, so changes in one appear in
|
||||||
|
* the other. The subset will throw an {@link IllegalArgumentException}
|
||||||
|
* for any attempt to access or add an element beyond the specified cutoffs.
|
||||||
|
* The returned set includes the low endpoint but not the high; if you want
|
||||||
|
* to reverse this behavior on either end, pass in the successor element.
|
||||||
|
*
|
||||||
|
* @param from the (inclusive) low cutoff point
|
||||||
|
* @param to the (exclusive) high cutoff point
|
||||||
|
* @return a view of the set between the cutoffs
|
||||||
|
* @throws ClassCastException if either cutoff is not compatible with
|
||||||
|
* the comparator (or is not Comparable, for natural ordering)
|
||||||
|
* @throws NullPointerException if from or to is null, but the comparator
|
||||||
|
* does not tolerate null elements
|
||||||
|
* @throws IllegalArgumentException if from is greater than to
|
||||||
|
*/
|
||||||
|
public SortedSet subSet(Object from, Object to)
|
||||||
|
{
|
||||||
|
return new TreeSet(map.subMap(from, to));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a view of this Set including all elements greater or equal to
|
||||||
|
* <code>from</code>. The returned set is backed by the original, so
|
||||||
|
* changes in one appear in the other. The subset will throw an
|
||||||
|
* {@link IllegalArgumentException} for any attempt to access or add an
|
||||||
|
* element beyond the specified cutoff. The returned set includes the
|
||||||
|
* endpoint; if you want to exclude it, pass in the successor element.
|
||||||
|
*
|
||||||
|
* @param from the (inclusive) low cutoff point
|
||||||
|
* @return a view of the set above the cutoff
|
||||||
|
* @throws ClassCastException if <code>from</code> is not compatible with
|
||||||
|
* the comparator (or is not Comparable, for natural ordering)
|
||||||
|
* @throws NullPointerException if from is null, but the comparator
|
||||||
|
* does not tolerate null elements
|
||||||
*/
|
*/
|
||||||
public SortedSet tailSet(Object from)
|
public SortedSet tailSet(Object from)
|
||||||
{
|
{
|
||||||
return new TreeSet(map.tailMap(from));
|
return new TreeSet(map.tailMap(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns in Iterator over the elements in this TreeSet */
|
/**
|
||||||
public Iterator iterator()
|
* Serializes this object to the given stream.
|
||||||
{
|
*
|
||||||
return map.keySet().iterator();
|
* @param s the stream to write to
|
||||||
}
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the <i>comparator</i> (Object), followed by the set size
|
||||||
private void writeObject(ObjectOutputStream out) throws IOException
|
* (int), the the elements in sorted order (Object)
|
||||||
|
*/
|
||||||
|
private void writeObject(ObjectOutputStream s) throws IOException
|
||||||
{
|
{
|
||||||
|
s.defaultWriteObject();
|
||||||
Iterator itr = map.keySet().iterator();
|
Iterator itr = map.keySet().iterator();
|
||||||
int size = map.size();
|
int pos = map.size();
|
||||||
|
s.writeObject(map.comparator());
|
||||||
out.writeObject(map.comparator());
|
s.writeInt(pos);
|
||||||
out.writeInt(size);
|
while (--pos >= 0)
|
||||||
|
s.writeObject(itr.next());
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
out.writeObject(itr.next());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readObject(ObjectInputStream in)
|
/**
|
||||||
|
* Deserializes this object from the given stream.
|
||||||
|
*
|
||||||
|
* @param s the stream to read from
|
||||||
|
* @throws ClassNotFoundException if the underlying stream fails
|
||||||
|
* @throws IOException if the underlying stream fails
|
||||||
|
* @serialData the <i>comparator</i> (Object), followed by the set size
|
||||||
|
* (int), the the elements in sorted order (Object)
|
||||||
|
*/
|
||||||
|
private void readObject(ObjectInputStream s)
|
||||||
throws IOException, ClassNotFoundException
|
throws IOException, ClassNotFoundException
|
||||||
{
|
{
|
||||||
Comparator comparator = (Comparator) in.readObject();
|
s.defaultReadObject();
|
||||||
int size = in.readInt();
|
Comparator comparator = (Comparator) s.readObject();
|
||||||
TreeMap map = new TreeMap(comparator);
|
int size = s.readInt();
|
||||||
map.putFromObjStream(in, size, false);
|
map = new TreeMap(comparator);
|
||||||
this.map = map;
|
((TreeMap) map).putFromObjStream(s, size, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue