+ * This class is a member of the
+ *
* Java Collections Framework.
*
* @author Josh Bloch
* @author Neal Gafter
- * @version 1.89, 07/28/04
- * @see Collection
- * @see Set
- * @see List
- * @see Map
+ * @see Collection
+ * @see Set
+ * @see List
+ * @see Map
* @since 1.2
*/
@@ -81,7 +91,7 @@ private Collections() {
* two implementations, one of which is appropriate for RandomAccess
* lists, the other for "sequential." Often, the random access variant
* yields better performance on small sequential access lists. The
- * tuning parameters below determine the cutoff point for what constitutes
+ * tuning parameters below determine the cutoff point for what constitutes
* a "small" sequential access list for each algorithm. The values below
* were empirically determined to work well for LinkedList. Hopefully
* they should be reasonable for other sequential access List
@@ -101,119 +111,103 @@ private Collections() {
/**
* Sorts the specified list into ascending order, according to the
- * natural ordering of its elements. All elements in the list must
- * implement the Comparable interface. Furthermore, all elements
- * in the list must be mutually comparable (that is,
- * e1.compareTo(e2) must not throw a ClassCastException
- * for any elements e1 and e2 in the list).
- *
- * This sort is guaranteed to be stable: equal elements will
- * not be reordered as a result of the sort.
+ * {@linkplain Comparable natural ordering} of its elements.
+ * All elements in the list must implement the {@link Comparable}
+ * interface. Furthermore, all elements in the list must be
+ * mutually comparable (that is, {@code e1.compareTo(e2)}
+ * must not throw a {@code ClassCastException} for any elements
+ * {@code e1} and {@code e2} in the list).
*
- * The specified list must be modifiable, but need not be resizable.
+ *
This sort is guaranteed to be stable: equal elements will
+ * not be reordered as a result of the sort.
*
- * The sorting algorithm is a modified mergesort (in which the merge is
- * omitted if the highest element in the low sublist is less than the
- * lowest element in the high sublist). This algorithm offers guaranteed
- * n log(n) performance.
+ *
The specified list must be modifiable, but need not be resizable.
*
- * This implementation dumps the specified list into an array, sorts
- * the array, and iterates over the list resetting each element
- * from the corresponding position in the array. This avoids the
- * n2 log(n) performance that would result from attempting
- * to sort a linked list in place.
+ * @implNote
+ * This implementation defers to the {@link List#sort(Comparator)}
+ * method using the specified list and a {@code null} comparator.
*
+ * @param the class of the objects in the list
* @param list the list to be sorted.
* @throws ClassCastException if the list contains elements that are not
- * mutually comparable (for example, strings and integers).
+ * mutually comparable (for example, strings and integers).
* @throws UnsupportedOperationException if the specified list's
- * list-iterator does not support the set operation.
- * @see Comparable
+ * list-iterator does not support the {@code set} operation.
+ * @throws IllegalArgumentException (optional) if the implementation
+ * detects that the natural ordering of the list elements is
+ * found to violate the {@link Comparable} contract
+ * @see List#sort(Comparator)
*/
+ @SuppressWarnings("unchecked")
public static > void sort(List list) {
- Object[] a = list.toArray();
- Arrays.sort(a);
- ListIterator i = list.listIterator();
- for (int j=0; jmutually
* comparable using the specified comparator (that is,
- * c.compare(e1, e2) must not throw a ClassCastException
- * for any elements e1 and e2 in the list).
+ * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+ * for any elements {@code e1} and {@code e2} in the list).
*
- * This sort is guaranteed to be stable: equal elements will
- * not be reordered as a result of the sort.
+ *
This sort is guaranteed to be stable: equal elements will
+ * not be reordered as a result of the sort.
*
- * The sorting algorithm is a modified mergesort (in which the merge is
- * omitted if the highest element in the low sublist is less than the
- * lowest element in the high sublist). This algorithm offers guaranteed
- * n log(n) performance.
+ *
The specified list must be modifiable, but need not be resizable.
*
- * The specified list must be modifiable, but need not be resizable.
- * This implementation dumps the specified list into an array, sorts
- * the array, and iterates over the list resetting each element
- * from the corresponding position in the array. This avoids the
- * n2 log(n) performance that would result from attempting
- * to sort a linked list in place.
+ * @implNote
+ * This implementation defers to the {@link List#sort(Comparator)}
+ * method using the specified list and comparator.
*
+ * @param the class of the objects in the list
* @param list the list to be sorted.
* @param c the comparator to determine the order of the list. A
- * null value indicates that the elements' natural
+ * {@code null} value indicates that the elements' natural
* ordering should be used.
* @throws ClassCastException if the list contains elements that are not
- * mutually comparable using the specified comparator.
+ * mutually comparable using the specified comparator.
* @throws UnsupportedOperationException if the specified list's
- * list-iterator does not support the set operation.
- * @see Comparator
+ * list-iterator does not support the {@code set} operation.
+ * @throws IllegalArgumentException (optional) if the comparator is
+ * found to violate the {@link Comparator} contract
+ * @see List#sort(Comparator)
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
public static void sort(List list, Comparator super T> c) {
- Object[] a = list.toArray();
- Arrays.sort(a, (Comparator)c);
- ListIterator i = list.listIterator();
- for (int j=0; jnatural ordering of its elements (as by the
- * sort(List) method, above) prior to making this call. If it is
- * not sorted, the results are undefined. If the list contains multiple
- * elements equal to the specified object, there is no guarantee which one
- * will be found.
+ * according to the {@linkplain Comparable natural ordering} of its
+ * elements (as by the {@link #sort(List)} method) prior to making this
+ * call. If it is not sorted, the results are undefined. If the list
+ * contains multiple elements equal to the specified object, there is no
+ * guarantee which one will be found.
*
- * This method runs in log(n) time for a "random access" list (which
+ *
This method runs in log(n) time for a "random access" list (which
* provides near-constant-time positional access). If the specified list
* does not implement the {@link RandomAccess} interface and is large,
* this method will do an iterator-based binary search that performs
* O(n) link traversals and O(log n) element comparisons.
*
+ * @param the class of the objects in the list
* @param list the list to be searched.
* @param key the key to be searched for.
- * @return index of the search key, if it is contained in the list;
- * otherwise, (-(insertion point) - 1). The
- * insertion point is defined as the point at which the
- * key would be inserted into the list: the index of the first
- * element greater than the key, or list.size(), if all
- * elements in the list are less than the specified key. Note
- * that this guarantees that the return value will be >= 0 if
- * and only if the key is found.
+ * @return the index of the search key, if it is contained in the list;
+ * otherwise, (-(insertion point) - 1). The
+ * insertion point is defined as the point at which the
+ * key would be inserted into the list: the index of the first
+ * element greater than the key, or list.size() if all
+ * elements in the list are less than the specified key. Note
+ * that this guarantees that the return value will be >= 0 if
+ * and only if the key is found.
* @throws ClassCastException if the list contains elements that are not
- * mutually comparable (for example, strings and
- * integers), or the search key in not mutually comparable
- * with the elements of the list.
- * @see Comparable
- * @see #sort(List)
+ * mutually comparable (for example, strings and
+ * integers), or the search key is not mutually comparable
+ * with the elements of the list.
*/
public static
int binarySearch(List extends Comparable super T>> list, T key) {
@@ -224,35 +218,34 @@ int binarySearch(List extends Comparable super T>> list, T key) {
}
private static
- int indexedBinarySearch(List extends Comparable super T>> list, T key)
- {
- int low = 0;
- int high = list.size()-1;
+ int indexedBinarySearch(List extends Comparable super T>> list, T key) {
+ int low = 0;
+ int high = list.size()-1;
- while (low <= high) {
- int mid = (low + high) >> 1;
- Comparable super T> midVal = list.get(mid);
- int cmp = midVal.compareTo(key);
+ while (low <= high) {
+ int mid = (low + high) >>> 1;
+ Comparable super T> midVal = list.get(mid);
+ int cmp = midVal.compareTo(key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found
+ if (cmp < 0)
+ low = mid + 1;
+ else if (cmp > 0)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found
}
private static
int iteratorBinarySearch(List extends Comparable super T>> list, T key)
{
- int low = 0;
- int high = list.size()-1;
+ int low = 0;
+ int high = list.size()-1;
ListIterator extends Comparable super T>> i = list.listIterator();
while (low <= high) {
- int mid = (low + high) >> 1;
+ int mid = (low + high) >>> 1;
Comparable super T> midVal = get(i, mid);
int cmp = midVal.compareTo(key);
@@ -271,7 +264,7 @@ else if (cmp > 0)
* list listIterator.
*/
private static T get(ListIterator extends T> i, int index) {
- T obj = null;
+ T obj = null;
int pos = i.nextIndex();
if (pos <= index) {
do {
@@ -288,41 +281,42 @@ private static T get(ListIterator extends T> i, int index) {
/**
* Searches the specified list for the specified object using the binary
* search algorithm. The list must be sorted into ascending order
- * according to the specified comparator (as by the Sort(List,
- * Comparator) method, above), prior to making this call. If it is
+ * according to the specified comparator (as by the
+ * {@link #sort(List, Comparator) sort(List, Comparator)}
+ * method), prior to making this call. If it is
* not sorted, the results are undefined. If the list contains multiple
* elements equal to the specified object, there is no guarantee which one
- * will be found.
+ * will be found.
*
- * This method runs in log(n) time for a "random access" list (which
+ *
This method runs in log(n) time for a "random access" list (which
* provides near-constant-time positional access). If the specified list
* does not implement the {@link RandomAccess} interface and is large,
* this method will do an iterator-based binary search that performs
* O(n) link traversals and O(log n) element comparisons.
*
+ * @param the class of the objects in the list
* @param list the list to be searched.
* @param key the key to be searched for.
- * @param c the comparator by which the list is ordered. A
- * null value indicates that the elements' natural
- * ordering should be used.
- * @return index of the search key, if it is contained in the list;
- * otherwise, (-(insertion point) - 1). The
- * insertion point is defined as the point at which the
- * key would be inserted into the list: the index of the first
- * element greater than the key, or list.size(), if all
- * elements in the list are less than the specified key. Note
- * that this guarantees that the return value will be >= 0 if
- * and only if the key is found.
+ * @param c the comparator by which the list is ordered.
+ * A null value indicates that the elements'
+ * {@linkplain Comparable natural ordering} should be used.
+ * @return the index of the search key, if it is contained in the list;
+ * otherwise, (-(insertion point) - 1). The
+ * insertion point is defined as the point at which the
+ * key would be inserted into the list: the index of the first
+ * element greater than the key, or list.size() if all
+ * elements in the list are less than the specified key. Note
+ * that this guarantees that the return value will be >= 0 if
+ * and only if the key is found.
* @throws ClassCastException if the list contains elements that are not
- * mutually comparable using the specified comparator,
- * or the search key in not mutually comparable with the
- * elements of the list using this comparator.
- * @see Comparable
- * @see #sort(List, Comparator)
+ * mutually comparable using the specified comparator,
+ * or the search key is not mutually comparable with the
+ * elements of the list using this comparator.
*/
+ @SuppressWarnings("unchecked")
public static int binarySearch(List extends T> list, T key, Comparator super T> c) {
if (c==null)
- return binarySearch((List) list, key);
+ return binarySearch((List extends Comparable super T>>) list, key);
if (list instanceof RandomAccess || list.size() int binarySearch(List extends T> list, T key, Comparator s
}
private static int indexedBinarySearch(List extends T> l, T key, Comparator super T> c) {
- int low = 0;
- int high = l.size()-1;
+ int low = 0;
+ int high = l.size()-1;
- while (low <= high) {
- int mid = (low + high) >> 1;
- T midVal = l.get(mid);
- int cmp = c.compare(midVal, key);
+ while (low <= high) {
+ int mid = (low + high) >>> 1;
+ T midVal = l.get(mid);
+ int cmp = c.compare(midVal, key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found
+ if (cmp < 0)
+ low = mid + 1;
+ else if (cmp > 0)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found
}
private static int iteratorBinarySearch(List extends T> l, T key, Comparator super T> c) {
- int low = 0;
- int high = l.size()-1;
+ int low = 0;
+ int high = l.size()-1;
ListIterator extends T> i = l.listIterator();
while (low <= high) {
- int mid = (low + high) >> 1;
+ int mid = (low + high) >>> 1;
T midVal = get(i, mid);
int cmp = c.compare(midVal, key);
@@ -369,9 +363,6 @@ else if (cmp > 0)
return -(low + 1); // key not found
}
- private interface SelfComparable extends Comparable {}
-
-
/**
* Reverses the order of the elements in the specified list.
*
@@ -379,18 +370,22 @@ private interface SelfComparable extends Comparable {}
*
* @param list the list whose elements are to be reversed.
* @throws UnsupportedOperationException if the specified list or
- * its list-iterator does not support the set method.
+ * its list-iterator does not support the set operation.
*/
+ @SuppressWarnings({"rawtypes", "unchecked"})
public static void reverse(List> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i>1; i list) {
/**
* Randomly permutes the specified list using a default source of
* randomness. All permutations occur with approximately equal
- * likelihood.
+ * likelihood.
*
- * The hedge "approximately" is used in the foregoing description because
+ *
The hedge "approximately" is used in the foregoing description because
* default source of randomness is only approximately an unbiased source
* of independently chosen bits. If it were a perfect source of randomly
* chosen bits, then the algorithm would choose permutations with perfect
- * uniformity.
+ * uniformity.
*
- * This implementation traverses the list backwards, from the last element
- * up to the second, repeatedly swapping a randomly selected element into
- * the "current position". Elements are randomly selected from the
+ *
This implementation traverses the list backwards, from the last
+ * element up to the second, repeatedly swapping a randomly selected element
+ * into the "current position". Elements are randomly selected from the
* portion of the list that runs from the first element to the current
- * position, inclusive.
+ * position, inclusive.
*
- * This method runs in linear time. If the specified list does not
+ *
This method runs in linear time. If the specified list does not
* implement the {@link RandomAccess} interface and is large, this
* implementation dumps the specified list into an array before shuffling
* it, and dumps the shuffled array back into the list. This avoids the
@@ -423,12 +418,16 @@ public static void reverse(List> list) {
*
* @param list the list to be shuffled.
* @throws UnsupportedOperationException if the specified list or
- * its list-iterator does not support the set method.
+ * its list-iterator does not support the set operation.
*/
public static void shuffle(List> list) {
- shuffle(list, r);
+ Random rnd = r;
+ if (rnd == null)
+ r = rnd = new Random(); // harmless race.
+ shuffle(list, rnd);
}
- private static Random r = new Random();
+
+ private static Random r;
/**
* Randomly permute the specified list using the specified source of
@@ -453,19 +452,23 @@ public static void shuffle(List> list) {
* @throws UnsupportedOperationException if the specified list or its
* list-iterator does not support the set operation.
*/
+ @SuppressWarnings({"rawtypes", "unchecked"})
public static void shuffle(List> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
- Object arr[] = list.toArray();
+ Object[] arr = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
+ // instead of using a raw type here, it's possible to capture
+ // the wildcard but it will require a call to a supplementary
+ // private method
ListIterator it = list.listIterator();
for (int i=0; i list, Random rnd) {
* || j < 0 || j >= list.size()).
* @since 1.4
*/
+ @SuppressWarnings({"rawtypes", "unchecked"})
public static void swap(List> list, int i, int j) {
- final List l = list;
- l.set(i, l.set(j, l.get(i)));
+ // instead of using a raw type here, it's possible to capture
+ // the wildcard but it will require a call to a supplementary
+ // private method
+ final List l = list;
+ l.set(i, l.set(j, l.get(i)));
}
/**
@@ -507,10 +514,11 @@ private static void swap(Object[] arr, int i, int j) {
*
* This method runs in linear time.
*
+ * @param the class of the objects in the list
* @param list the list to be filled with the specified element.
* @param obj The element with which to fill the specified list.
* @throws UnsupportedOperationException if the specified list or its
- * list-iterator does not support the set operation.
+ * list-iterator does not support the set operation.
*/
public static void fill(List super T> list, T obj) {
int size = list.size();
@@ -536,6 +544,7 @@ public static void fill(List super T> list, T obj) {
*
* This method runs in linear time.
*
+ * @param the class of the objects in the lists
* @param dest The destination list.
* @param src The source list.
* @throws IndexOutOfBoundsException if the destination list is too small
@@ -549,12 +558,12 @@ public static void copy(List super T> dest, List extends T> src) {
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
- (src instanceof RandomAccess && dest instanceof RandomAccess)) {
+ (src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i di=dest.listIterator();
- ListIterator extends T> si=src.listIterator();
+ ListIterator extends T> si=src.listIterator();
for (int i=0; i void copy(List super T> dest, List extends T> src) {
* This method iterates over the entire collection, hence it requires
* time proportional to the size of the collection.
*
+ * @param the class of the objects in the collection
* @param coll the collection whose minimum element is to be determined.
* @return the minimum element of the given collection, according
* to the natural ordering of its elements.
* @throws ClassCastException if the collection contains elements that are
- * not mutually comparable (for example, strings and
- * integers).
+ * not mutually comparable (for example, strings and
+ * integers).
* @throws NoSuchElementException if the collection is empty.
* @see Comparable
*/
public static > T min(Collection extends T> coll) {
- Iterator extends T> i = coll.iterator();
- T candidate = i.next();
+ Iterator extends T> i = coll.iterator();
+ T candidate = i.next();
- while(i.hasNext()) {
- T next = i.next();
- if (next.compareTo(candidate) < 0)
- candidate = next;
- }
- return candidate;
+ while (i.hasNext()) {
+ T next = i.next();
+ if (next.compareTo(candidate) < 0)
+ candidate = next;
+ }
+ return candidate;
}
/**
@@ -606,6 +616,7 @@ public static > T min(Collection exte
* This method iterates over the entire collection, hence it requires
* time proportional to the size of the collection.
*
+ * @param the class of the objects in the collection
* @param coll the collection whose minimum element is to be determined.
* @param comp the comparator with which to determine the minimum element.
* A null value indicates that the elements' natural
@@ -613,23 +624,24 @@ public static > T min(Collection exte
* @return the minimum element of the given collection, according
* to the specified comparator.
* @throws ClassCastException if the collection contains elements that are
- * not mutually comparable using the specified comparator.
+ * not mutually comparable using the specified comparator.
* @throws NoSuchElementException if the collection is empty.
* @see Comparable
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
public static T min(Collection extends T> coll, Comparator super T> comp) {
if (comp==null)
- return (T)min((Collection) (Collection) coll);
+ return (T)min((Collection) coll);
- Iterator extends T> i = coll.iterator();
- T candidate = i.next();
+ Iterator extends T> i = coll.iterator();
+ T candidate = i.next();
- while(i.hasNext()) {
- T next = i.next();
- if (comp.compare(next, candidate) < 0)
- candidate = next;
- }
- return candidate;
+ while (i.hasNext()) {
+ T next = i.next();
+ if (comp.compare(next, candidate) < 0)
+ candidate = next;
+ }
+ return candidate;
}
/**
@@ -644,25 +656,26 @@ public static T min(Collection extends T> coll, Comparator super T> comp
* This method iterates over the entire collection, hence it requires
* time proportional to the size of the collection.
*
+ * @param the class of the objects in the collection
* @param coll the collection whose maximum element is to be determined.
* @return the maximum element of the given collection, according
* to the natural ordering of its elements.
* @throws ClassCastException if the collection contains elements that are
- * not mutually comparable (for example, strings and
+ * not mutually comparable (for example, strings and
* integers).
* @throws NoSuchElementException if the collection is empty.
* @see Comparable
*/
public static > T max(Collection extends T> coll) {
- Iterator extends T> i = coll.iterator();
- T candidate = i.next();
+ Iterator extends T> i = coll.iterator();
+ T candidate = i.next();
- while(i.hasNext()) {
- T next = i.next();
- if (next.compareTo(candidate) > 0)
- candidate = next;
- }
- return candidate;
+ while (i.hasNext()) {
+ T next = i.next();
+ if (next.compareTo(candidate) > 0)
+ candidate = next;
+ }
+ return candidate;
}
/**
@@ -676,6 +689,7 @@ public static > T max(Collection exte
* This method iterates over the entire collection, hence it requires
* time proportional to the size of the collection.
*
+ * @param the class of the objects in the collection
* @param coll the collection whose maximum element is to be determined.
* @param comp the comparator with which to determine the maximum element.
* A null value indicates that the elements' natural
@@ -683,23 +697,24 @@ public static > T max(Collection exte
* @return the maximum element of the given collection, according
* to the specified comparator.
* @throws ClassCastException if the collection contains elements that are
- * not mutually comparable using the specified comparator.
+ * not mutually comparable using the specified comparator.
* @throws NoSuchElementException if the collection is empty.
* @see Comparable
*/
+ @SuppressWarnings({"unchecked", "rawtypes"})
public static T max(Collection extends T> coll, Comparator super T> comp) {
if (comp==null)
- return (T)max((Collection) (Collection) coll);
+ return (T)max((Collection) coll);
- Iterator extends T> i = coll.iterator();
- T candidate = i.next();
+ Iterator extends T> i = coll.iterator();
+ T candidate = i.next();
- while(i.hasNext()) {
- T next = i.next();
- if (comp.compare(next, candidate) > 0)
- candidate = next;
- }
- return candidate;
+ while (i.hasNext()) {
+ T next = i.next();
+ if (comp.compare(next, candidate) > 0)
+ candidate = next;
+ }
+ return candidate;
}
/**
@@ -730,7 +745,7 @@ public static T max(Collection extends T> coll, Comparator super T> comp
* Collections.rotate(l.subList(1, 4), -1);
*
* The resulting list is [a, c, d, b, e].
- *
+ *
* To move more than one element forward, increase the absolute value
* of the rotation distance. To move elements backward, use a positive
* shift distance.
@@ -754,14 +769,14 @@ public static T max(Collection extends T> coll, Comparator super T> comp
* constraints on this value; it may be zero, negative, or
* greater than list.size().
* @throws UnsupportedOperationException if the specified list or
- * its list-iterator does not support the set method.
+ * its list-iterator does not support the set operation.
* @since 1.4
*/
public static void rotate(List> list, int distance) {
if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
- rotate1((List)list, distance);
+ rotate1(list, distance);
else
- rotate2((List)list, distance);
+ rotate2(list, distance);
}
private static void rotate1(List list, int distance) {
@@ -783,14 +798,14 @@ private static void rotate1(List list, int distance) {
i -= size;
displaced = list.set(i, displaced);
nMoved ++;
- } while(i != cycleStart);
+ } while (i != cycleStart);
}
}
private static void rotate2(List> list, int distance) {
int size = list.size();
if (size == 0)
- return;
+ return;
int mid = -distance % size;
if (mid < 0)
mid += size;
@@ -809,6 +824,7 @@ private static void rotate2(List> list, int distance) {
* (oldVal==null ? e==null : oldVal.equals(e)).
* (This method has no effect on the size of the list.)
*
+ * @param the class of the objects in the list
* @param list the list in which replacement is to occur.
* @param oldVal the old value to be replaced.
* @param newVal the new value with which oldVal is to be
@@ -817,7 +833,7 @@ private static void rotate2(List> list, int distance) {
* e such that
* (oldVal==null ? e==null : oldVal.equals(e)).
* @throws UnsupportedOperationException if the specified list or
- * its list-iterator does not support the set method.
+ * its list-iterator does not support the set operation.
* @since 1.4
*/
public static boolean replaceAll(List list, T oldVal, T newVal) {
@@ -864,9 +880,9 @@ public static boolean replaceAll(List list, T oldVal, T newVal) {
* Returns the starting position of the first occurrence of the specified
* target list within the specified source list, or -1 if there is no
* such occurrence. More formally, returns the lowest index i
- * such that source.subList(i, i+target.size()).equals(target),
+ * such that {@code source.subList(i, i+target.size()).equals(target)},
* or -1 if there is no such index. (Returns -1 if
- * target.size() > source.size().)
+ * {@code target.size() > source.size()})
*
* This implementation uses the "brute force" technique of scanning
* over the source list, looking for a match with the target at each
@@ -886,8 +902,8 @@ public static int indexOfSubList(List> source, List> target) {
int maxCandidate = sourceSize - targetSize;
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
- (source instanceof RandomAccess&&target instanceof RandomAccess)) {
- nextCand:
+ (source instanceof RandomAccess&&target instanceof RandomAccess)) {
+ nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
for (int i=0, j=candidate; i source, List> target) {
}
} else { // Iterator version of above algorithm
ListIterator> si = source.listIterator();
- nextCand:
+ nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
ListIterator> ti = target.listIterator();
for (int i=0; i source, List> target) {
* Returns the starting position of the last occurrence of the specified
* target list within the specified source list, or -1 if there is no such
* occurrence. More formally, returns the highest index i
- * such that source.subList(i, i+target.size()).equals(target),
+ * such that {@code source.subList(i, i+target.size()).equals(target)},
* or -1 if there is no such index. (Returns -1 if
- * target.size() > source.size().)
+ * {@code target.size() > source.size()})
*
* This implementation uses the "brute force" technique of iterating
* over the source list, looking for a match with the target at each
@@ -939,8 +955,8 @@ public static int lastIndexOfSubList(List> source, List> target) {
int maxCandidate = sourceSize - targetSize;
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
- source instanceof RandomAccess) { // Index access version
- nextCand:
+ source instanceof RandomAccess) { // Index access version
+ nextCand:
for (int candidate = maxCandidate; candidate >= 0; candidate--) {
for (int i=0, j=candidate; i source, List> target) {
if (maxCandidate < 0)
return -1;
ListIterator> si = source.listIterator(maxCandidate);
- nextCand:
+ nextCand:
for (int candidate = maxCandidate; candidate >= 0; candidate--) {
ListIterator> ti = target.listIterator();
for (int i=0; i source, List> target) {
* that the backing collection is a set or a list.
*
* The returned collection will be serializable if the specified collection
- * is serializable.
+ * is serializable.
*
+ * @param the class of the objects in the collection
* @param c the collection for which an unmodifiable view is to be
- * returned.
+ * returned.
* @return an unmodifiable view of the specified collection.
*/
public static Collection unmodifiableCollection(Collection extends T> c) {
- return new UnmodifiableCollection(c);
+ return new UnmodifiableCollection<>(c);
}
/**
* @serial include
*/
- static class UnmodifiableCollection implements Collection {
- // use serialVersionUID from JDK 1.2.2 for interoperability
- private static final long serialVersionUID = 1820017752578914078L;
+ static class UnmodifiableCollection implements Collection, Serializable {
+ private static final long serialVersionUID = 1820017752578914078L;
- Collection extends E> c;
+ final Collection extends E> c;
- UnmodifiableCollection(Collection extends E> c) {
+ UnmodifiableCollection(Collection extends E> c) {
if (c==null)
throw new NullPointerException();
this.c = c;
}
- public int size() {return c.size();}
- public boolean isEmpty() {return c.isEmpty();}
- public boolean contains(Object o) {return c.contains(o);}
- public Object[] toArray() {return c.toArray();}
- public T[] toArray(T[] a) {return c.toArray(a);}
+ public int size() {return c.size();}
+ public boolean isEmpty() {return c.isEmpty();}
+ public boolean contains(Object o) {return c.contains(o);}
+ public Object[] toArray() {return c.toArray();}
+ public T[] toArray(T[] a) {return c.toArray(a);}
public String toString() {return c.toString();}
- public Iterator iterator() {
- return new Iterator() {
- Iterator extends E> i = c.iterator();
+ public Iterator iterator() {
+ return new Iterator() {
+ private final Iterator extends E> i = c.iterator();
- public boolean hasNext() {return i.hasNext();}
- public E next() {return i.next();}
- public void remove() {
- throw new UnsupportedOperationException();
+ public boolean hasNext() {return i.hasNext();}
+ public E next() {return i.next();}
+ public void remove() {
+ throw new UnsupportedOperationException();
}
- };
+ @Override
+ public void forEachRemaining(Consumer super E> action) {
+ // Use backing collection version
+ i.forEachRemaining(action);
+ }
+ };
}
- public boolean add(E o){
- throw new UnsupportedOperationException();
+ public boolean add(E e) {
+ throw new UnsupportedOperationException();
}
- public boolean remove(Object o) {
- throw new UnsupportedOperationException();
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
}
- public boolean containsAll(Collection> coll) {
- return c.containsAll(coll);
+ public boolean containsAll(Collection> coll) {
+ return c.containsAll(coll);
+ }
+ public boolean addAll(Collection extends E> coll) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean removeAll(Collection> coll) {
+ throw new UnsupportedOperationException();
+ }
+ public boolean retainAll(Collection> coll) {
+ throw new UnsupportedOperationException();
}
- public boolean addAll(Collection extends E> coll) {
- throw new UnsupportedOperationException();
+ public void clear() {
+ throw new UnsupportedOperationException();
}
- public boolean removeAll(Collection> coll) {
- throw new UnsupportedOperationException();
+
+ // Override default methods in Collection
+ @Override
+ public void forEach(Consumer super E> action) {
+ c.forEach(action);
}
- public boolean retainAll(Collection> coll) {
- throw new UnsupportedOperationException();
+ @Override
+ public boolean removeIf(Predicate super E> filter) {
+ throw new UnsupportedOperationException();
}
- public void clear() {
- throw new UnsupportedOperationException();
+ @SuppressWarnings("unchecked")
+ @Override
+ public Spliterator spliterator() {
+ return (Spliterator)c.spliterator();
}
+// @SuppressWarnings("unchecked")
+// @Override
+// public Stream stream() {
+// return (Stream)c.stream();
+// }
+// @SuppressWarnings("unchecked")
+// @Override
+// public Stream parallelStream() {
+// return (Stream)c.parallelStream();
+// }
}
/**
@@ -1064,26 +1110,26 @@ public void clear() {
* iterator, result in an UnsupportedOperationException.
*
* The returned set will be serializable if the specified set
- * is serializable.
+ * is serializable.
*
+ * @param the class of the objects in the set
* @param s the set for which an unmodifiable view is to be returned.
* @return an unmodifiable view of the specified set.
*/
-
public static Set unmodifiableSet(Set extends T> s) {
- return new UnmodifiableSet(s);
+ return new UnmodifiableSet<>(s);
}
/**
* @serial include
*/
static class UnmodifiableSet extends UnmodifiableCollection
- implements Set{
- private static final long serialVersionUID = -9215047833775013803L;
+ implements Set, Serializable {
+ private static final long serialVersionUID = -9215047833775013803L;
- UnmodifiableSet(Set extends E> s) {super(s);}
- public boolean equals(Object o) {return c.equals(o);}
- public int hashCode() {return c.hashCode();}
+ UnmodifiableSet(Set extends E> s) {super(s);}
+ public boolean equals(Object o) {return o == this || c.equals(o);}
+ public int hashCode() {return c.hashCode();}
}
/**
@@ -1096,41 +1142,131 @@ static class UnmodifiableSet extends UnmodifiableCollection
* an UnsupportedOperationException.
*
* The returned sorted set will be serializable if the specified sorted set
- * is serializable.
+ * is serializable.
*
+ * @param the class of the objects in the set
* @param s the sorted set for which an unmodifiable view is to be
- * returned.
+ * returned.
* @return an unmodifiable view of the specified sorted set.
*/
public static SortedSet unmodifiableSortedSet(SortedSet s) {
- return new UnmodifiableSortedSet(s);
+ return new UnmodifiableSortedSet<>(s);
}
/**
* @serial include
*/
static class UnmodifiableSortedSet
- extends UnmodifiableSet
- implements SortedSet{
- private static final long serialVersionUID = -4929149591599911165L;
- private SortedSet ss;
+ extends UnmodifiableSet
+ implements SortedSet, Serializable {
+ private static final long serialVersionUID = -4929149591599911165L;
+ private final SortedSet ss;
- UnmodifiableSortedSet(SortedSet s) {super(s); ss = s;}
+ UnmodifiableSortedSet(SortedSet s) {super(s); ss = s;}
public Comparator super E> comparator() {return ss.comparator();}
public SortedSet subSet(E fromElement, E toElement) {
- return new UnmodifiableSortedSet(ss.subSet(fromElement,toElement));
+ return new UnmodifiableSortedSet<>(ss.subSet(fromElement,toElement));
}
public SortedSet headSet(E toElement) {
- return new UnmodifiableSortedSet(ss.headSet(toElement));
+ return new UnmodifiableSortedSet<>(ss.headSet(toElement));
}
public SortedSet tailSet(E fromElement) {
- return new UnmodifiableSortedSet(ss.tailSet(fromElement));
+ return new UnmodifiableSortedSet<>(ss.tailSet(fromElement));
+ }
+
+ public E first() {return ss.first();}
+ public E last() {return ss.last();}
+ }
+
+ /**
+ * Returns an unmodifiable view of the specified navigable set. This method
+ * allows modules to provide users with "read-only" access to internal
+ * navigable sets. Query operations on the returned navigable set "read
+ * through" to the specified navigable set. Attempts to modify the returned
+ * navigable set, whether direct, via its iterator, or via its
+ * {@code subSet}, {@code headSet}, or {@code tailSet} views, result in
+ * an {@code UnsupportedOperationException}.
+ *
+ * The returned navigable set will be serializable if the specified
+ * navigable set is serializable.
+ *
+ * @param the class of the objects in the set
+ * @param s the navigable set for which an unmodifiable view is to be
+ * returned
+ * @return an unmodifiable view of the specified navigable set
+ * @since 1.8
+ */
+ public static NavigableSet unmodifiableNavigableSet(NavigableSet s) {
+ return new UnmodifiableNavigableSet<>(s);
+ }
+
+ /**
+ * Wraps a navigable set and disables all of the mutative operations.
+ *
+ * @param type of elements
+ * @serial include
+ */
+ static class UnmodifiableNavigableSet
+ extends UnmodifiableSortedSet
+ implements NavigableSet, Serializable {
+
+ private static final long serialVersionUID = -6027448201786391929L;
+
+ /**
+ * A singleton empty unmodifiable navigable set used for
+ * {@link #emptyNavigableSet()}.
+ *
+ * @param type of elements, if there were any, and bounds
+ */
+ private static class EmptyNavigableSet extends UnmodifiableNavigableSet
+ implements Serializable {
+ private static final long serialVersionUID = -6291252904449939134L;
+
+ public EmptyNavigableSet() {
+ super(new TreeSet());
+ }
+
+ private Object readResolve() { return EMPTY_NAVIGABLE_SET; }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private static final NavigableSet> EMPTY_NAVIGABLE_SET =
+ new EmptyNavigableSet<>();
+
+ /**
+ * The instance we are protecting.
+ */
+ private final NavigableSet ns;
+
+ UnmodifiableNavigableSet(NavigableSet s) {super(s); ns = s;}
+
+ public E lower(E e) { return ns.lower(e); }
+ public E floor(E e) { return ns.floor(e); }
+ public E ceiling(E e) { return ns.ceiling(e); }
+ public E higher(E e) { return ns.higher(e); }
+ public E pollFirst() { throw new UnsupportedOperationException(); }
+ public E pollLast() { throw new UnsupportedOperationException(); }
+ public NavigableSet descendingSet()
+ { return new UnmodifiableNavigableSet<>(ns.descendingSet()); }
+ public Iterator descendingIterator()
+ { return descendingSet().iterator(); }
+
+ public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.subSet(fromElement, fromInclusive, toElement, toInclusive));
+ }
+
+ public NavigableSet headSet(E toElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.headSet(toElement, inclusive));
}
- public E first() {return ss.first();}
- public E last() {return ss.last();}
+ public NavigableSet tailSet(E fromElement, boolean inclusive) {
+ return new UnmodifiableNavigableSet<>(
+ ns.tailSet(fromElement, inclusive));
+ }
}
/**
@@ -1145,73 +1281,91 @@ public SortedSet tailSet(E fromElement) {
* is serializable. Similarly, the returned list will implement
* {@link RandomAccess} if the specified list does.
*
+ * @param the class of the objects in the list
* @param list the list for which an unmodifiable view is to be returned.
* @return an unmodifiable view of the specified list.
*/
public static List unmodifiableList(List extends T> list) {
- return (list instanceof RandomAccess ?
- new UnmodifiableRandomAccessList(list) :
- new UnmodifiableList(list));
+ return (list instanceof RandomAccess ?
+ new UnmodifiableRandomAccessList<>(list) :
+ new UnmodifiableList<>(list));
}
/**
* @serial include
*/
static class UnmodifiableList extends UnmodifiableCollection
- implements List {
- static final long serialVersionUID = -283967356065247728L;
- List extends E> list;
+ implements List {
+ private static final long serialVersionUID = -283967356065247728L;
+
+ final List extends E> list;
- UnmodifiableList(List extends E> list) {
- super(list);
- this.list = list;
- }
+ UnmodifiableList(List extends E> list) {
+ super(list);
+ this.list = list;
+ }
- public boolean equals(Object o) {return list.equals(o);}
- public int hashCode() {return list.hashCode();}
+ public boolean equals(Object o) {return o == this || list.equals(o);}
+ public int hashCode() {return list.hashCode();}
- public E get(int index) {return list.get(index);}
- public E set(int index, E element) {
- throw new UnsupportedOperationException();
+ public E get(int index) {return list.get(index);}
+ public E set(int index, E element) {
+ throw new UnsupportedOperationException();
+ }
+ public void add(int index, E element) {
+ throw new UnsupportedOperationException();
}
- public void add(int index, E element) {
- throw new UnsupportedOperationException();
+ public E remove(int index) {
+ throw new UnsupportedOperationException();
}
- public E remove(int index) {
- throw new UnsupportedOperationException();
+ public int indexOf(Object o) {return list.indexOf(o);}
+ public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
+ public boolean addAll(int index, Collection extends E> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void replaceAll(UnaryOperator operator) {
+ throw new UnsupportedOperationException();
}
- public int indexOf(Object o) {return list.indexOf(o);}
- public int lastIndexOf(Object o) {return list.lastIndexOf(o);}
- public boolean addAll(int index, Collection extends E> c) {
- throw new UnsupportedOperationException();
+ @Override
+ public void sort(Comparator super E> c) {
+ throw new UnsupportedOperationException();
}
- public ListIterator listIterator() {return listIterator(0);}
- public ListIterator listIterator(final int index) {
- return new ListIterator() {
- ListIterator extends E> i = list.listIterator(index);
+ public ListIterator listIterator() {return listIterator(0);}
+
+ public ListIterator listIterator(final int index) {
+ return new ListIterator() {
+ private final ListIterator extends E> i
+ = list.listIterator(index);
- public boolean hasNext() {return i.hasNext();}
- public E next() {return i.next();}
- public boolean hasPrevious() {return i.hasPrevious();}
- public E previous() {return i.previous();}
- public int nextIndex() {return i.nextIndex();}
- public int previousIndex() {return i.previousIndex();}
+ public boolean hasNext() {return i.hasNext();}
+ public E next() {return i.next();}
+ public boolean hasPrevious() {return i.hasPrevious();}
+ public E previous() {return i.previous();}
+ public int nextIndex() {return i.nextIndex();}
+ public int previousIndex() {return i.previousIndex();}
- public void remove() {
- throw new UnsupportedOperationException();
+ public void remove() {
+ throw new UnsupportedOperationException();
}
- public void set(E o) {
- throw new UnsupportedOperationException();
+ public void set(E e) {
+ throw new UnsupportedOperationException();
+ }
+ public void add(E e) {
+ throw new UnsupportedOperationException();
}
- public void add(E o) {
- throw new UnsupportedOperationException();
+
+ @Override
+ public void forEachRemaining(Consumer super E> action) {
+ i.forEachRemaining(action);
}
- };
- }
+ };
+ }
- public List subList(int fromIndex, int toIndex) {
- return new UnmodifiableList(list.subList(fromIndex, toIndex));
+ public List subList(int fromIndex, int toIndex) {
+ return new UnmodifiableList<>(list.subList(fromIndex, toIndex));
}
/**
@@ -1228,8 +1382,8 @@ public List subList(int fromIndex, int toIndex) {
*/
private Object readResolve() {
return (list instanceof RandomAccess
- ? new UnmodifiableRandomAccessList(list)
- : this);
+ ? new UnmodifiableRandomAccessList<>(list)
+ : this);
}
}
@@ -1237,15 +1391,15 @@ private Object readResolve() {
* @serial include
*/
static class UnmodifiableRandomAccessList extends UnmodifiableList
- implements RandomAccess
+ implements RandomAccess
{
UnmodifiableRandomAccessList(List extends E> list) {
super(list);
}
- public List subList(int fromIndex, int toIndex) {
- return new UnmodifiableRandomAccessList(
- list.subList(fromIndex, toIndex));
+ public List subList(int fromIndex, int toIndex) {
+ return new UnmodifiableRandomAccessList<>(
+ list.subList(fromIndex, toIndex));
}
private static final long serialVersionUID = -2542308836966382001L;
@@ -1257,7 +1411,7 @@ public List subList(int fromIndex, int toIndex) {
* deserialization.
*/
private Object writeReplace() {
- return new UnmodifiableList(list);
+ return new UnmodifiableList<>(list);
}
}
@@ -1270,75 +1424,137 @@ private Object writeReplace() {
* UnsupportedOperationException.
*
* The returned map will be serializable if the specified map
- * is serializable.
+ * is serializable.
*
+ * @param the class of the map keys
+ * @param the class of the map values
* @param m the map for which an unmodifiable view is to be returned.
* @return an unmodifiable view of the specified map.
*/
public static Map unmodifiableMap(Map extends K, ? extends V> m) {
- return new UnmodifiableMap(m);
+ return new UnmodifiableMap<>(m);
}
/**
* @serial include
*/
- private static class UnmodifiableMap implements Map {
- // use serialVersionUID from JDK 1.2.2 for interoperability
- private static final long serialVersionUID = -1034234728574286014L;
+ private static class UnmodifiableMap implements Map, Serializable {
+ private static final long serialVersionUID = -1034234728574286014L;
- private final Map extends K, ? extends V> m;
+ private final Map extends K, ? extends V> m;
- UnmodifiableMap(Map extends K, ? extends V> m) {
+ UnmodifiableMap(Map extends K, ? extends V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
}
- public int size() {return m.size();}
- public boolean isEmpty() {return m.isEmpty();}
- public boolean containsKey(Object key) {return m.containsKey(key);}
- public boolean containsValue(Object val) {return m.containsValue(val);}
- public V get(Object key) {return m.get(key);}
+ public int size() {return m.size();}
+ public boolean isEmpty() {return m.isEmpty();}
+ public boolean containsKey(Object key) {return m.containsKey(key);}
+ public boolean containsValue(Object val) {return m.containsValue(val);}
+ public V get(Object key) {return m.get(key);}
- public V put(K key, V value) {
- throw new UnsupportedOperationException();
+ public V put(K key, V value) {
+ throw new UnsupportedOperationException();
}
- public V remove(Object key) {
- throw new UnsupportedOperationException();
+ public V remove(Object key) {
+ throw new UnsupportedOperationException();
}
- public void putAll(Map extends K, ? extends V> t) {
- throw new UnsupportedOperationException();
+ public void putAll(Map extends K, ? extends V> m) {
+ throw new UnsupportedOperationException();
}
- public void clear() {
- throw new UnsupportedOperationException();
+ public void clear() {
+ throw new UnsupportedOperationException();
}
- private transient Set keySet = null;
- private transient Set> entrySet = null;
- private transient Collection values = null;
+ private transient Set keySet;
+ private transient Set> entrySet;
+ private transient Collection values;
- public Set keySet() {
- if (keySet==null)
- keySet = unmodifiableSet(m.keySet());
- return keySet;
- }
+ public Set keySet() {
+ if (keySet==null)
+ keySet = unmodifiableSet(m.keySet());
+ return keySet;
+ }
- public Set> entrySet() {
- if (entrySet==null)
- entrySet = new UnmodifiableEntrySet(m.entrySet());
- return entrySet;
- }
+ public Set> entrySet() {
+ if (entrySet==null)
+ entrySet = new UnmodifiableEntrySet<>(m.entrySet());
+ return entrySet;
+ }
- public Collection values() {
- if (values==null)
- values = unmodifiableCollection(m.values());
- return values;
- }
+ public Collection values() {
+ if (values==null)
+ values = unmodifiableCollection(m.values());
+ return values;
+ }
- public boolean equals(Object o) {return m.equals(o);}
- public int hashCode() {return m.hashCode();}
+ public boolean equals(Object o) {return o == this || m.equals(o);}
+ public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();}
+ // Override default methods in Map
+ @Override
+ @SuppressWarnings("unchecked")
+ public V getOrDefault(Object k, V defaultValue) {
+ // Safe cast as we don't change the value
+ return ((Map)m).getOrDefault(k, defaultValue);
+ }
+
+ @Override
+ public void forEach(BiConsumer super K, ? super V> action) {
+ m.forEach(action);
+ }
+
+ @Override
+ public void replaceAll(BiFunction super K, ? super V, ? extends V> function) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V putIfAbsent(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean replace(K key, V oldValue, V newValue) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V replace(K key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V computeIfPresent(K key,
+ BiFunction super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V compute(K key,
+ BiFunction super K, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public V merge(K key, V value,
+ BiFunction super V, ? super V, ? extends V> remappingFunction) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map
@@ -1348,47 +1564,127 @@ public Collection values() {
* @serial include
*/
static class UnmodifiableEntrySet
- extends UnmodifiableSet> {
- private static final long serialVersionUID = 7854390611657943733L;
+ extends UnmodifiableSet> {
+ private static final long serialVersionUID = 7854390611657943733L;
+ @SuppressWarnings({"unchecked", "rawtypes"})
UnmodifiableEntrySet(Set extends Map.Entry extends K, ? extends V>> s) {
- super((Set>)(Set)s);
+ // Need to cast to raw in order to work around a limitation in the type system
+ super((Set)s);
}
- public Iterator> iterator() {
- return new Iterator>() {
- Iterator extends Map.Entry extends K, ? extends V>> i = c.iterator();
- public boolean hasNext() {
- return i.hasNext();
- }
- public Map.Entry next() {
- return new UnmodifiableEntry(i.next());
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
+ static Consumer> entryConsumer(Consumer super Entry> action) {
+ return e -> action.accept(new UnmodifiableEntry<>(e));
+ }
+
+ public void forEach(Consumer super Entry> action) {
+ Objects.requireNonNull(action);
+ c.forEach(entryConsumer(action));
+ }
+
+ static final class UnmodifiableEntrySetSpliterator
+ implements Spliterator> {
+ final Spliterator> s;
+
+ UnmodifiableEntrySetSpliterator(Spliterator> s) {
+ this.s = s;
+ }
+
+ @Override
+ public boolean tryAdvance(Consumer super Entry> action) {
+ Objects.requireNonNull(action);
+ return s.tryAdvance(entryConsumer(action));
+ }
+
+ @Override
+ public void forEachRemaining(Consumer super Entry> action) {
+ Objects.requireNonNull(action);
+ s.forEachRemaining(entryConsumer(action));
+ }
+
+ @Override
+ public Spliterator> trySplit() {
+ Spliterator> split = s.trySplit();
+ return split == null
+ ? null
+ : new UnmodifiableEntrySetSpliterator<>(split);
+ }
+
+ @Override
+ public long estimateSize() {
+ return s.estimateSize();
+ }
+
+ @Override
+ public long getExactSizeIfKnown() {
+ return s.getExactSizeIfKnown();
+ }
+
+ @Override
+ public int characteristics() {
+ return s.characteristics();
+ }
+
+ @Override
+ public boolean hasCharacteristics(int characteristics) {
+ return s.hasCharacteristics(characteristics);
+ }
+
+ @Override
+ public Comparator super Entry> getComparator() {
+ return s.getComparator();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public Spliterator> spliterator() {
+ return new UnmodifiableEntrySetSpliterator<>(
+ (Spliterator>) c.spliterator());
}
+// @Override
+// public Stream> stream() {
+// return StreamSupport.stream(spliterator(), false);
+// }
+//
+// @Override
+// public Stream> parallelStream() {
+// return StreamSupport.stream(spliterator(), true);
+// }
+//
+// public Iterator> iterator() {
+// return new Iterator>() {
+// private final Iterator extends Map.Entry extends K, ? extends V>> i = c.iterator();
+//
+// public boolean hasNext() {
+// return i.hasNext();
+// }
+// public Map.Entry next() {
+// return new UnmodifiableEntry<>(i.next());
+// }
+// public void remove() {
+// throw new UnsupportedOperationException();
+// }
+// };
+// }
+
+ @SuppressWarnings("unchecked")
public Object[] toArray() {
Object[] a = c.toArray();
for (int i=0; i((Map.Entry)a[i]);
+ a[i] = new UnmodifiableEntry<>((Map.Entry extends K, ? extends V>)a[i]);
return a;
}
+ @SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
// We don't pass a to c.toArray, to avoid window of
// vulnerability wherein an unscrupulous multithreaded client
// could get his hands on raw (unwrapped) Entries from c.
- Object[] arr =
- c.toArray(
- a.length==0 ? a :
- (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), 0)
- );
+ Object[] arr = c.toArray(a.length==0 ? a : Arrays.copyOf(a, 0));
for (int i=0; i((Map.Entry)arr[i]);
+ arr[i] = new UnmodifiableEntry<>((Map.Entry extends K, ? extends V>)arr[i]);
if (arr.length > a.length)
return (T[])arr;
@@ -1408,7 +1704,8 @@ public T[] toArray(T[] a) {
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
- return c.contains(new UnmodifiableEntry((Map.Entry) o));
+ return c.contains(
+ new UnmodifiableEntry<>((Map.Entry,?>) o));
}
/**
@@ -1417,10 +1714,10 @@ public boolean contains(Object o) {
* when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection> coll) {
- Iterator> e = coll.iterator();
- while (e.hasNext())
- if (!contains(e.next())) // Invokes safe contains() above
+ for (Object e : coll) {
+ if (!contains(e)) // Invokes safe contains() above
return false;
+ }
return true;
}
public boolean equals(Object o) {
@@ -1429,7 +1726,7 @@ public boolean equals(Object o) {
if (!(o instanceof Set))
return false;
- Set s = (Set) o;
+ Set> s = (Set>) o;
if (s.size() != c.size())
return false;
return containsAll(s); // Invokes safe containsAll() above
@@ -1445,22 +1742,25 @@ public boolean equals(Object o) {
private static class UnmodifiableEntry implements Map.Entry {
private Map.Entry extends K, ? extends V> e;
- UnmodifiableEntry(Map.Entry extends K, ? extends V> e) {this.e = e;}
+ UnmodifiableEntry(Map.Entry extends K, ? extends V> e)
+ {this.e = Objects.requireNonNull(e);}
- public K getKey() {return e.getKey();}
- public V getValue() {return e.getValue();}
+ public K getKey() {return e.getKey();}
+ public V getValue() {return e.getValue();}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
- public int hashCode() {return e.hashCode();}
+ public int hashCode() {return e.hashCode();}
public boolean equals(Object o) {
+ if (this == o)
+ return true;
if (!(o instanceof Map.Entry))
return false;
- Map.Entry t = (Map.Entry)o;
+ Map.Entry,?> t = (Map.Entry,?>)o;
return eq(e.getKey(), t.getKey()) &&
- eq(e.getValue(), t.getValue());
+ eq(e.getValue(), t.getValue());
}
- public String toString() {return e.toString();}
+ public String toString() {return e.toString();}
}
}
}
@@ -1475,44 +1775,181 @@ public boolean equals(Object o) {
* an UnsupportedOperationException.
*
* The returned sorted map will be serializable if the specified sorted map
- * is serializable.
+ * is serializable.
*
+ * @param the class of the map keys
+ * @param the class of the map values
* @param m the sorted map for which an unmodifiable view is to be
- * returned.
+ * returned.
* @return an unmodifiable view of the specified sorted map.
*/
public static SortedMap unmodifiableSortedMap(SortedMap m) {
- return new UnmodifiableSortedMap(m);
+ return new UnmodifiableSortedMap<>(m);
}
/**
* @serial include
*/
static class UnmodifiableSortedMap
- extends UnmodifiableMap
- implements SortedMap {
- private static final long serialVersionUID = -8806743815996713206L;
+ extends UnmodifiableMap
+ implements SortedMap, Serializable {
+ private static final long serialVersionUID = -8806743815996713206L;
+
+ private final SortedMap sm;
+
+ UnmodifiableSortedMap(SortedMap