Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
java.util.Collections Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util;
import java.io.*;
import java.lang.reflect.Array;
/**
* {@code Collections} contains static methods which operate on
* {@code Collection} classes.
*
* @since 1.2
*/
public class Collections {
private static final Iterator> EMPTY_ITERATOR = new Iterator() {
@Override public boolean hasNext() {
return false;
}
@Override public Object next() {
throw new NoSuchElementException();
}
@Override public void remove() {
throw new IllegalStateException();
}
};
private static final Enumeration> EMPTY_ENUMERATION = new Enumeration() {
@Override public boolean hasMoreElements() {
return false;
}
@Override public Object nextElement() {
throw new NoSuchElementException();
}
};
private static final class CopiesList extends AbstractList implements Serializable {
private final int n;
private final E element;
CopiesList(int length, E object) {
if (length < 0) {
throw new IllegalArgumentException("length < 0: " + length);
}
n = length;
element = object;
}
@Override public boolean contains(Object object) {
return element == null ? object == null : element.equals(object);
}
@Override public int size() {
return n;
}
@Override public E get(int location) {
if (location >= 0 && location < n) {
return element;
}
throw new IndexOutOfBoundsException();
}
}
@SuppressWarnings("unchecked")
private static final class EmptyList extends AbstractList implements RandomAccess, Serializable {
@Override public boolean contains(Object object) {
return false;
}
@Override public int size() {
return 0;
}
@Override public Object get(int location) {
throw new IndexOutOfBoundsException();
}
private Object readResolve() {
return Collections.EMPTY_LIST;
}
}
@SuppressWarnings("unchecked")
private static final class EmptySet extends AbstractSet implements Serializable {
@Override public boolean contains(Object object) {
return false;
}
@Override public int size() {
return 0;
}
@Override public Iterator iterator() {
return EMPTY_ITERATOR;
}
private Object readResolve() {
return Collections.EMPTY_SET;
}
}
@SuppressWarnings("unchecked")
private static final class EmptyMap extends AbstractMap implements Serializable {
@Override public boolean containsKey(Object key) {
return false;
}
@Override public boolean containsValue(Object value) {
return false;
}
@Override public Set entrySet() {
return EMPTY_SET;
}
@Override public Object get(Object key) {
return null;
}
@Override public Set keySet() {
return EMPTY_SET;
}
@Override public Collection values() {
return EMPTY_LIST;
}
private Object readResolve() {
return Collections.EMPTY_MAP;
}
}
/**
* An empty immutable instance of {@link List}.
*/
@SuppressWarnings("unchecked")
public static final List EMPTY_LIST = new EmptyList();
/**
* An empty immutable instance of {@link Set}.
*/
@SuppressWarnings("unchecked")
public static final Set EMPTY_SET = new EmptySet();
/**
* An empty immutable instance of {@link Map}.
*/
@SuppressWarnings("unchecked")
public static final Map EMPTY_MAP = new EmptyMap();
/**
* This class is a singleton so that equals() and hashCode() work properly.
*/
private static final class ReverseComparator implements Comparator, Serializable {
private static final ReverseComparator INSTANCE = new ReverseComparator();
@SuppressWarnings("unchecked")
@Override public int compare(T o1, T o2) {
Comparable c2 = (Comparable) o2;
return c2.compareTo(o1);
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
}
private static final class ReverseComparator2 implements Comparator, Serializable {
private final Comparator cmp;
ReverseComparator2(Comparator comparator) {
this.cmp = comparator;
}
@Override public int compare(T o1, T o2) {
return cmp.compare(o2, o1);
}
@Override public boolean equals(Object o) {
return o instanceof ReverseComparator2
&& ((ReverseComparator2) o).cmp.equals(cmp);
}
@Override public int hashCode() {
return ~cmp.hashCode();
}
}
private static final class SingletonSet extends AbstractSet implements Serializable {
final E element;
SingletonSet(E object) {
element = object;
}
@Override public boolean contains(Object object) {
return element == null ? object == null : element.equals(object);
}
@Override public int size() {
return 1;
}
@Override public Iterator iterator() {
return new Iterator() {
boolean hasNext = true;
@Override public boolean hasNext() {
return hasNext;
}
@Override public E next() {
if (hasNext) {
hasNext = false;
return element;
}
throw new NoSuchElementException();
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
private static final class SingletonList extends AbstractList implements Serializable {
final E element;
SingletonList(E object) {
element = object;
}
@Override public boolean contains(Object object) {
return element == null ? object == null : element.equals(object);
}
@Override public E get(int location) {
if (location == 0) {
return element;
}
throw new IndexOutOfBoundsException();
}
@Override public int size() {
return 1;
}
}
private static final class SingletonMap extends AbstractMap implements Serializable {
final K k;
final V v;
SingletonMap(K key, V value) {
k = key;
v = value;
}
@Override public boolean containsKey(Object key) {
return k == null ? key == null : k.equals(key);
}
@Override public boolean containsValue(Object value) {
return v == null ? value == null : v.equals(value);
}
@Override public V get(Object key) {
if (containsKey(key)) {
return v;
}
return null;
}
@Override public int size() {
return 1;
}
@Override public Set> entrySet() {
return new AbstractSet>() {
@Override public boolean contains(Object object) {
if (object instanceof Entry) {
Entry, ?> entry = (Entry, ?>) object;
return containsKey(entry.getKey())
&& containsValue(entry.getValue());
}
return false;
}
@Override public int size() {
return 1;
}
@Override public Iterator> iterator() {
return new Iterator>() {
boolean hasNext = true;
@Override public boolean hasNext() {
return hasNext;
}
@Override public Entry next() {
if (!hasNext) {
throw new NoSuchElementException();
}
hasNext = false;
return new MapEntry(k, v) {
@Override public V setValue(V value) {
throw new UnsupportedOperationException();
}
};
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
}
static class SynchronizedCollection implements Collection, Serializable {
final Collection c;
final Object mutex;
SynchronizedCollection(Collection collection) {
c = collection;
mutex = this;
}
SynchronizedCollection(Collection collection, Object mutex) {
c = collection;
this.mutex = mutex;
}
@Override public boolean add(E object) {
synchronized (mutex) {
return c.add(object);
}
}
@Override public boolean addAll(Collection extends E> collection) {
synchronized (mutex) {
return c.addAll(collection);
}
}
@Override public void clear() {
synchronized (mutex) {
c.clear();
}
}
@Override public boolean contains(Object object) {
synchronized (mutex) {
return c.contains(object);
}
}
@Override public boolean containsAll(Collection> collection) {
synchronized (mutex) {
return c.containsAll(collection);
}
}
@Override public boolean isEmpty() {
synchronized (mutex) {
return c.isEmpty();
}
}
@Override public Iterator iterator() {
synchronized (mutex) {
return c.iterator();
}
}
@Override public boolean remove(Object object) {
synchronized (mutex) {
return c.remove(object);
}
}
@Override public boolean removeAll(Collection> collection) {
synchronized (mutex) {
return c.removeAll(collection);
}
}
@Override public boolean retainAll(Collection> collection) {
synchronized (mutex) {
return c.retainAll(collection);
}
}
@Override public int size() {
synchronized (mutex) {
return c.size();
}
}
@Override public Object[] toArray() {
synchronized (mutex) {
return c.toArray();
}
}
@Override public String toString() {
synchronized (mutex) {
return c.toString();
}
}
@Override public T[] toArray(T[] array) {
synchronized (mutex) {
return c.toArray(array);
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
}
static class SynchronizedRandomAccessList extends SynchronizedList implements RandomAccess {
SynchronizedRandomAccessList(List l) {
super(l);
}
SynchronizedRandomAccessList(List l, Object mutex) {
super(l, mutex);
}
@Override public List subList(int start, int end) {
synchronized (mutex) {
return new SynchronizedRandomAccessList(list.subList(start, end), mutex);
}
}
/**
* Replaces this SynchronizedRandomAccessList with a SynchronizedList so
* that JREs before 1.4 can deserialize this object without any
* problems. This is necessary since RandomAccess API was introduced
* only in 1.4.
*
*
* @return SynchronizedList
*
* @see SynchronizedList#readResolve()
*/
private Object writeReplace() {
return new SynchronizedList(list);
}
}
static class SynchronizedList extends SynchronizedCollection implements List {
final List list;
SynchronizedList(List l) {
super(l);
list = l;
}
SynchronizedList(List l, Object mutex) {
super(l, mutex);
list = l;
}
@Override public void add(int location, E object) {
synchronized (mutex) {
list.add(location, object);
}
}
@Override public boolean addAll(int location, Collection extends E> collection) {
synchronized (mutex) {
return list.addAll(location, collection);
}
}
@Override public boolean equals(Object object) {
synchronized (mutex) {
return list.equals(object);
}
}
@Override public E get(int location) {
synchronized (mutex) {
return list.get(location);
}
}
@Override public int hashCode() {
synchronized (mutex) {
return list.hashCode();
}
}
@Override public int indexOf(Object object) {
final int size;
final Object[] array;
synchronized (mutex) {
size = list.size();
array = new Object[size];
list.toArray(array);
}
if (object != null) {
for (int i = 0; i < size; i++) {
if (object.equals(array[i])) {
return i;
}
}
} else {
for (int i = 0; i < size; i++) {
if (array[i] == null) {
return i;
}
}
}
return -1;
}
@Override public int lastIndexOf(Object object) {
final int size;
final Object[] array;
synchronized (mutex) {
size = list.size();
array = new Object[size];
list.toArray(array);
}
if (object != null) {
for (int i = size - 1; i >= 0; i--) {
if (object.equals(array[i])) {
return i;
}
}
} else {
for (int i = size - 1; i >= 0; i--) {
if (array[i] == null) {
return i;
}
}
}
return -1;
}
@Override public ListIterator listIterator() {
synchronized (mutex) {
return list.listIterator();
}
}
@Override public ListIterator listIterator(int location) {
synchronized (mutex) {
return list.listIterator(location);
}
}
@Override public E remove(int location) {
synchronized (mutex) {
return list.remove(location);
}
}
@Override public E set(int location, E object) {
synchronized (mutex) {
return list.set(location, object);
}
}
@Override public List subList(int start, int end) {
synchronized (mutex) {
return new SynchronizedList(list.subList(start, end), mutex);
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
/**
* Resolves SynchronizedList instances to SynchronizedRandomAccessList
* instances if the underlying list is a Random Access list.
*
* This is necessary since SynchronizedRandomAccessList instances are
* replaced with SynchronizedList instances during serialization for
* compliance with JREs before 1.4.
*
*
* @return a SynchronizedList instance if the underlying list implements
* RandomAccess interface, or this same object if not.
*
* @see SynchronizedRandomAccessList#writeReplace()
*/
private Object readResolve() {
if (list instanceof RandomAccess) {
return new SynchronizedRandomAccessList(list, mutex);
}
return this;
}
}
static class SynchronizedMap implements Map, Serializable {
private final Map m;
final Object mutex;
SynchronizedMap(Map map) {
m = map;
mutex = this;
}
SynchronizedMap(Map map, Object mutex) {
m = map;
this.mutex = mutex;
}
@Override public void clear() {
synchronized (mutex) {
m.clear();
}
}
@Override public boolean containsKey(Object key) {
synchronized (mutex) {
return m.containsKey(key);
}
}
@Override public boolean containsValue(Object value) {
synchronized (mutex) {
return m.containsValue(value);
}
}
@Override public Set> entrySet() {
synchronized (mutex) {
return new SynchronizedSet>(m.entrySet(), mutex);
}
}
@Override public boolean equals(Object object) {
synchronized (mutex) {
return m.equals(object);
}
}
@Override public V get(Object key) {
synchronized (mutex) {
return m.get(key);
}
}
@Override public int hashCode() {
synchronized (mutex) {
return m.hashCode();
}
}
@Override public boolean isEmpty() {
synchronized (mutex) {
return m.isEmpty();
}
}
@Override public Set keySet() {
synchronized (mutex) {
return new SynchronizedSet(m.keySet(), mutex);
}
}
@Override public V put(K key, V value) {
synchronized (mutex) {
return m.put(key, value);
}
}
@Override public void putAll(Map extends K, ? extends V> map) {
synchronized (mutex) {
m.putAll(map);
}
}
@Override public V remove(Object key) {
synchronized (mutex) {
return m.remove(key);
}
}
@Override public int size() {
synchronized (mutex) {
return m.size();
}
}
@Override public Collection values() {
synchronized (mutex) {
return new SynchronizedCollection(m.values(), mutex);
}
}
@Override public String toString() {
synchronized (mutex) {
return m.toString();
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
}
static class SynchronizedSet extends SynchronizedCollection implements Set {
SynchronizedSet(Set set) {
super(set);
}
SynchronizedSet(Set set, Object mutex) {
super(set, mutex);
}
@Override public boolean equals(Object object) {
synchronized (mutex) {
return c.equals(object);
}
}
@Override public int hashCode() {
synchronized (mutex) {
return c.hashCode();
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
}
static class SynchronizedSortedMap extends SynchronizedMap implements SortedMap {
private final SortedMap sm;
SynchronizedSortedMap(SortedMap map) {
super(map);
sm = map;
}
SynchronizedSortedMap(SortedMap map, Object mutex) {
super(map, mutex);
sm = map;
}
@Override public Comparator super K> comparator() {
synchronized (mutex) {
return sm.comparator();
}
}
@Override public K firstKey() {
synchronized (mutex) {
return sm.firstKey();
}
}
@Override public SortedMap headMap(K endKey) {
synchronized (mutex) {
return new SynchronizedSortedMap(sm.headMap(endKey),
mutex);
}
}
@Override public K lastKey() {
synchronized (mutex) {
return sm.lastKey();
}
}
@Override public SortedMap subMap(K startKey, K endKey) {
synchronized (mutex) {
return new SynchronizedSortedMap(sm.subMap(startKey,
endKey), mutex);
}
}
@Override public SortedMap tailMap(K startKey) {
synchronized (mutex) {
return new SynchronizedSortedMap(sm.tailMap(startKey),
mutex);
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
}
static class SynchronizedSortedSet extends SynchronizedSet implements SortedSet {
private final SortedSet ss;
SynchronizedSortedSet(SortedSet set) {
super(set);
ss = set;
}
SynchronizedSortedSet(SortedSet set, Object mutex) {
super(set, mutex);
ss = set;
}
@Override public Comparator super E> comparator() {
synchronized (mutex) {
return ss.comparator();
}
}
@Override public E first() {
synchronized (mutex) {
return ss.first();
}
}
@Override public SortedSet headSet(E end) {
synchronized (mutex) {
return new SynchronizedSortedSet(ss.headSet(end), mutex);
}
}
@Override public E last() {
synchronized (mutex) {
return ss.last();
}
}
@Override public SortedSet subSet(E start, E end) {
synchronized (mutex) {
return new SynchronizedSortedSet(ss.subSet(start, end),
mutex);
}
}
@Override public SortedSet tailSet(E start) {
synchronized (mutex) {
return new SynchronizedSortedSet(ss.tailSet(start), mutex);
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
synchronized (mutex) {
stream.defaultWriteObject();
}
}
}
private static class UnmodifiableCollection implements Collection, Serializable {
final Collection c;
UnmodifiableCollection(Collection collection) {
c = collection;
}
@Override public boolean add(E object) {
throw new UnsupportedOperationException();
}
@Override public boolean addAll(Collection extends E> collection) {
throw new UnsupportedOperationException();
}
@Override public void clear() {
throw new UnsupportedOperationException();
}
@Override public boolean contains(Object object) {
return c.contains(object);
}
@Override public boolean containsAll(Collection> collection) {
return c.containsAll(collection);
}
@Override public boolean isEmpty() {
return c.isEmpty();
}
@Override public Iterator iterator() {
return new Iterator() {
Iterator iterator = c.iterator();
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public E next() {
return iterator.next();
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public boolean remove(Object object) {
throw new UnsupportedOperationException();
}
@Override public boolean removeAll(Collection> collection) {
throw new UnsupportedOperationException();
}
@Override public boolean retainAll(Collection> collection) {
throw new UnsupportedOperationException();
}
@Override public int size() {
return c.size();
}
@Override public Object[] toArray() {
return c.toArray();
}
@Override public T[] toArray(T[] array) {
return c.toArray(array);
}
@Override public String toString() {
return c.toString();
}
}
private static class UnmodifiableRandomAccessList extends UnmodifiableList implements RandomAccess {
UnmodifiableRandomAccessList(List l) {
super(l);
}
@Override public List subList(int start, int end) {
return new UnmodifiableRandomAccessList(list.subList(start, end));
}
/**
* Replaces this UnmodifiableRandomAccessList with an UnmodifiableList
* so that JREs before 1.4 can deserialize this object without any
* problems. This is necessary since RandomAccess API was introduced
* only in 1.4.
*
*
* @return UnmodifiableList
*
* @see UnmodifiableList#readResolve()
*/
private Object writeReplace() {
return new UnmodifiableList(list);
}
}
private static class UnmodifiableList extends UnmodifiableCollection implements List {
final List list;
UnmodifiableList(List l) {
super(l);
list = l;
}
@Override public void add(int location, E object) {
throw new UnsupportedOperationException();
}
@Override public boolean addAll(int location, Collection extends E> collection) {
throw new UnsupportedOperationException();
}
@Override public boolean equals(Object object) {
return list.equals(object);
}
@Override public E get(int location) {
return list.get(location);
}
@Override public int hashCode() {
return list.hashCode();
}
@Override public int indexOf(Object object) {
return list.indexOf(object);
}
@Override public int lastIndexOf(Object object) {
return list.lastIndexOf(object);
}
@Override public ListIterator listIterator() {
return listIterator(0);
}
@Override public ListIterator listIterator(final int location) {
return new ListIterator() {
ListIterator iterator = list.listIterator(location);
@Override public void add(E object) {
throw new UnsupportedOperationException();
}
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public boolean hasPrevious() {
return iterator.hasPrevious();
}
@Override public E next() {
return iterator.next();
}
@Override public int nextIndex() {
return iterator.nextIndex();
}
@Override public E previous() {
return iterator.previous();
}
@Override public int previousIndex() {
return iterator.previousIndex();
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
@Override public void set(E object) {
throw new UnsupportedOperationException();
}
};
}
@Override public E remove(int location) {
throw new UnsupportedOperationException();
}
@Override public E set(int location, E object) {
throw new UnsupportedOperationException();
}
@Override public List subList(int start, int end) {
return new UnmodifiableList(list.subList(start, end));
}
/**
* Resolves UnmodifiableList instances to UnmodifiableRandomAccessList
* instances if the underlying list is a Random Access list.
*
* This is necessary since UnmodifiableRandomAccessList instances are
* replaced with UnmodifiableList instances during serialization for
* compliance with JREs before 1.4.
*
*
* @return an UnmodifiableList instance if the underlying list
* implements RandomAccess interface, or this same object if
* not.
*
* @see UnmodifiableRandomAccessList#writeReplace()
*/
private Object readResolve() {
if (list instanceof RandomAccess) {
return new UnmodifiableRandomAccessList(list);
}
return this;
}
}
private static class UnmodifiableMap implements Map, Serializable {
private final Map m;
private static class UnmodifiableEntrySet extends UnmodifiableSet> {
private static class UnmodifiableMapEntry implements Entry {
Entry mapEntry;
UnmodifiableMapEntry(Entry entry) {
mapEntry = entry;
}
@Override public boolean equals(Object object) {
return mapEntry.equals(object);
}
@Override public K getKey() {
return mapEntry.getKey();
}
@Override public V getValue() {
return mapEntry.getValue();
}
@Override public int hashCode() {
return mapEntry.hashCode();
}
@Override public V setValue(V object) {
throw new UnsupportedOperationException();
}
@Override public String toString() {
return mapEntry.toString();
}
}
UnmodifiableEntrySet(Set> set) {
super(set);
}
@Override public Iterator> iterator() {
return new Iterator>() {
Iterator> iterator = c.iterator();
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public Entry next() {
return new UnmodifiableMapEntry(iterator.next());
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
};
}
@Override public Object[] toArray() {
int length = c.size();
Object[] result = new Object[length];
Iterator> it = iterator();
for (int i = length; --i >= 0;) {
result[i] = it.next();
}
return result;
}
@SuppressWarnings("unchecked")
@Override public T[] toArray(T[] contents) {
int size = c.size(), index = 0;
Iterator> it = iterator();
if (size > contents.length) {
Class> ct = contents.getClass().getComponentType();
contents = (T[]) Array.newInstance(ct, size);
}
while (index < size) {
contents[index++] = (T) it.next();
}
if (index < contents.length) {
contents[index] = null;
}
return contents;
}
}
UnmodifiableMap(Map map) {
m = map;
}
@Override public void clear() {
throw new UnsupportedOperationException();
}
@Override public boolean containsKey(Object key) {
return m.containsKey(key);
}
@Override public boolean containsValue(Object value) {
return m.containsValue(value);
}
@Override public Set> entrySet() {
return new UnmodifiableEntrySet(m.entrySet());
}
@Override public boolean equals(Object object) {
return m.equals(object);
}
@Override public V get(Object key) {
return m.get(key);
}
@Override public int hashCode() {
return m.hashCode();
}
@Override public boolean isEmpty() {
return m.isEmpty();
}
@Override public Set keySet() {
return new UnmodifiableSet(m.keySet());
}
@Override public V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Override public void putAll(Map extends K, ? extends V> map) {
throw new UnsupportedOperationException();
}
@Override public V remove(Object key) {
throw new UnsupportedOperationException();
}
@Override public int size() {
return m.size();
}
@Override public Collection values() {
return new UnmodifiableCollection(m.values());
}
@Override public String toString() {
return m.toString();
}
}
private static class UnmodifiableSet extends UnmodifiableCollection implements Set {
UnmodifiableSet(Set set) {
super(set);
}
@Override public boolean equals(Object object) {
return c.equals(object);
}
@Override public int hashCode() {
return c.hashCode();
}
}
private static class UnmodifiableSortedMap extends UnmodifiableMap implements SortedMap {
private final SortedMap sm;
UnmodifiableSortedMap(SortedMap map) {
super(map);
sm = map;
}
@Override public Comparator super K> comparator() {
return sm.comparator();
}
@Override public K firstKey() {
return sm.firstKey();
}
@Override public SortedMap headMap(K before) {
return new UnmodifiableSortedMap(sm.headMap(before));
}
@Override public K lastKey() {
return sm.lastKey();
}
@Override public SortedMap subMap(K start, K end) {
return new UnmodifiableSortedMap(sm.subMap(start, end));
}
@Override public SortedMap tailMap(K after) {
return new UnmodifiableSortedMap(sm.tailMap(after));
}
}
private static class UnmodifiableSortedSet extends UnmodifiableSet implements SortedSet {
private final SortedSet ss;
UnmodifiableSortedSet(SortedSet set) {
super(set);
ss = set;
}
@Override public Comparator super E> comparator() {
return ss.comparator();
}
@Override public E first() {
return ss.first();
}
@Override public SortedSet headSet(E before) {
return new UnmodifiableSortedSet(ss.headSet(before));
}
@Override public E last() {
return ss.last();
}
@Override public SortedSet subSet(E start, E end) {
return new UnmodifiableSortedSet(ss.subSet(start, end));
}
@Override public SortedSet tailSet(E after) {
return new UnmodifiableSortedSet(ss.tailSet(after));
}
}
private Collections() {}
/**
* Performs a binary search for the specified element in the specified
* sorted list. The list needs to be already sorted in natural sorting
* order. Searching in an unsorted array has an undefined result. It's also
* undefined which element is found if there are multiple occurrences of the
* same element.
*
* @param list
* the sorted list to search.
* @param object
* the element to find.
* @return the non-negative index of the element, or a negative index which
* is the {@code -index - 1} where the element would be inserted
* @throws ClassCastException
* if an element in the List or the search element does not
* implement Comparable, or cannot be compared to each other.
*/
@SuppressWarnings("unchecked")
public static int binarySearch(List extends Comparable super T>> list, T object) {
if (list == null) {
throw new NullPointerException("list == null");
}
if (list.isEmpty()) {
return -1;
}
if (!(list instanceof RandomAccess)) {
ListIterator extends Comparable super T>> it = list.listIterator();
while (it.hasNext()) {
int result;
if ((result = -it.next().compareTo(object)) <= 0) {
if (result == 0) {
return it.previousIndex();
}
return -it.previousIndex() - 1;
}
}
return -list.size() - 1;
}
int low = 0, mid = list.size(), high = mid - 1, result = -1;
while (low <= high) {
mid = (low + high) >>> 1;
if ((result = -list.get(mid).compareTo(object)) > 0) {
low = mid + 1;
} else if (result == 0) {
return mid;
} else {
high = mid - 1;
}
}
return -mid - (result < 0 ? 1 : 2);
}
/**
* Performs a binary search for the specified element in the specified
* sorted list using the specified comparator. The list needs to be already
* sorted according to the comparator passed. Searching in an unsorted array
* has an undefined result. It's also undefined which element is found if
* there are multiple occurrences of the same element.
*
* @param list
* the sorted List to search.
* @param object
* the element to find.
* @param comparator
* the comparator. If the comparator is {@code null} then the
* search uses the objects' natural ordering.
* @return the non-negative index of the element, or a negative index which
* is the {@code -index - 1} where the element would be inserted.
* @throws ClassCastException
* when an element in the list and the searched element cannot
* be compared to each other using the comparator.
*/
@SuppressWarnings("unchecked")
public static int binarySearch(List extends T> list, T object,
Comparator super T> comparator) {
if (comparator == null) {
return Collections.binarySearch(
(List extends Comparable super T>>) list, object);
}
if (!(list instanceof RandomAccess)) {
ListIterator extends T> it = list.listIterator();
while (it.hasNext()) {
int result;
if ((result = -comparator.compare(it.next(), object)) <= 0) {
if (result == 0) {
return it.previousIndex();
}
return -it.previousIndex() - 1;
}
}
return -list.size() - 1;
}
int low = 0, mid = list.size(), high = mid - 1, result = -1;
while (low <= high) {
mid = (low + high) >>> 1;
if ((result = -comparator.compare(list.get(mid), object)) > 0) {
low = mid + 1;
} else if (result == 0) {
return mid;
} else {
high = mid - 1;
}
}
return -mid - (result < 0 ? 1 : 2);
}
/**
* Copies the elements from the source list to the destination list. At the
* end both lists will have the same objects at the same index. If the
* destination array is larger than the source list, the elements in the
* destination list with {@code index >= source.size()} will be unchanged.
*
* @param destination
* the list whose elements are set from the source list.
* @param source
* the list with the elements to be copied into the destination.
* @throws IndexOutOfBoundsException
* when the destination list is smaller than the source list.
* @throws UnsupportedOperationException
* when replacing an element in the destination list is not
* supported.
*/
public static void copy(List super T> destination, List extends T> source) {
if (destination.size() < source.size()) {
throw new IndexOutOfBoundsException("destination.size() < source.size(): " +
destination.size() + " < " + source.size());
}
Iterator extends T> srcIt = source.iterator();
ListIterator super T> destIt = destination.listIterator();
while (srcIt.hasNext()) {
try {
destIt.next();
} catch (NoSuchElementException e) {
// TODO: AssertionError?
throw new IndexOutOfBoundsException("Source size " + source.size() +
" does not fit into destination");
}
destIt.set(srcIt.next());
}
}
/**
* Returns an {@code Enumeration} on the specified collection.
*
* @param collection
* the collection to enumerate.
* @return an Enumeration.
*/
public static Enumeration enumeration(Collection collection) {
final Collection c = collection;
return new Enumeration() {
Iterator it = c.iterator();
@Override public boolean hasMoreElements() {
return it.hasNext();
}
@Override public T nextElement() {
return it.next();
}
};
}
/**
* Fills the specified list with the specified element.
*
* @param list
* the list to fill.
* @param object
* the element to fill the list with.
* @throws UnsupportedOperationException
* when replacing an element in the List is not supported.
*/
public static void fill(List super T> list, T object) {
ListIterator super T> it = list.listIterator();
while (it.hasNext()) {
it.next();
it.set(object);
}
}
/**
* Searches the specified collection for the maximum element.
*
* @param collection
* the collection to search.
* @return the maximum element in the Collection.
* @throws ClassCastException
* when an element in the collection does not implement
* {@code Comparable} or elements cannot be compared to each
* other.
*/
public static > T max(
Collection extends T> collection) {
Iterator extends T> it = collection.iterator();
T max = it.next();
while (it.hasNext()) {
T next = it.next();
if (max.compareTo(next) < 0) {
max = next;
}
}
return max;
}
/**
* Searches the specified collection for the maximum element using the
* specified comparator.
*
* @param collection
* the collection to search.
* @param comparator
* the comparator.
* @return the maximum element in the Collection.
* @throws ClassCastException
* when elements in the collection cannot be compared to each
* other using the {@code Comparator}.
*/
public static T max(Collection extends T> collection,
Comparator super T> comparator) {
if (comparator == null) {
@SuppressWarnings("unchecked") // null comparator? T is comparable
T result = (T) max((Collection) collection);
return result;
}
Iterator extends T> it = collection.iterator();
T max = it.next();
while (it.hasNext()) {
T next = it.next();
if (comparator.compare(max, next) < 0) {
max = next;
}
}
return max;
}
/**
* Searches the specified collection for the minimum element.
*
* @param collection
* the collection to search.
* @return the minimum element in the collection.
* @throws ClassCastException
* when an element in the collection does not implement
* {@code Comparable} or elements cannot be compared to each
* other.
*/
public static > T min(
Collection extends T> collection) {
Iterator extends T> it = collection.iterator();
T min = it.next();
while (it.hasNext()) {
T next = it.next();
if (min.compareTo(next) > 0) {
min = next;
}
}
return min;
}
/**
* Searches the specified collection for the minimum element using the
* specified comparator.
*
* @param collection
* the collection to search.
* @param comparator
* the comparator.
* @return the minimum element in the collection.
* @throws ClassCastException
* when elements in the collection cannot be compared to each
* other using the {@code Comparator}.
*/
public static T min(Collection extends T> collection,
Comparator super T> comparator) {
if (comparator == null) {
@SuppressWarnings("unchecked") // null comparator? T is comparable
T result = (T) min((Collection) collection);
return result;
}
Iterator extends T> it = collection.iterator();
T min = it.next();
while (it.hasNext()) {
T next = it.next();
if (comparator.compare(min, next) > 0) {
min = next;
}
}
return min;
}
/**
* Returns a list containing the specified number of the specified element.
* The list cannot be modified. The list is serializable.
*
* @param length
* the size of the returned list.
* @param object
* the element to be added {@code length} times to a list.
* @return a list containing {@code length} copies of the element.
* @throws IllegalArgumentException
* when {@code length < 0}.
*/
public static List nCopies(final int length, T object) {
return new CopiesList(length, object);
}
/**
* Modifies the specified {@code List} by reversing the order of the
* elements.
*
* @param list
* the list to reverse.
* @throws UnsupportedOperationException
* when replacing an element in the List is not supported.
*/
@SuppressWarnings("unchecked")
public static void reverse(List> list) {
int size = list.size();
ListIterator front = (ListIterator) list.listIterator();
ListIterator back = (ListIterator) list.listIterator(size);
for (int i = 0; i < size / 2; i++) {
Object frontNext = front.next();
Object backPrev = back.previous();
front.set(backPrev);
back.set(frontNext);
}
}
/**
* A comparator which reverses the natural order of the elements. The
* {@code Comparator} that's returned is {@link Serializable}.
*
* @return a {@code Comparator} instance.
*/
@SuppressWarnings("unchecked")
public static Comparator reverseOrder() {
return (Comparator) ReverseComparator.INSTANCE;
}
/**
* Returns a {@link Comparator} that reverses the order of the
* {@code Comparator} passed. If the {@code Comparator} passed is
* {@code null}, then this method is equivalent to {@link #reverseOrder()}.
*
* The {@code Comparator} that's returned is {@link Serializable} if the
* {@code Comparator} passed is serializable or {@code null}.
*
* @param c
* the {@code Comparator} to reverse or {@code null}.
* @return a {@code Comparator} instance.
* @since 1.5
*/
public static Comparator reverseOrder(Comparator c) {
if (c == null) {
return reverseOrder();
}
if (c instanceof ReverseComparator2) {
return ((ReverseComparator2) c).cmp;
}
return new ReverseComparator2(c);
}
/**
* Moves every element of the list to a random new position in the list.
*
* @param list
* the List to shuffle.
*
* @throws UnsupportedOperationException
* when replacing an element in the List is not supported.
*/
public static void shuffle(List> list) {
shuffle(list, new Random());
}
/**
* Moves every element of the list to a random new position in the list
* using the specified random number generator.
*
* @param list
* the list to shuffle.
* @param random
* the random number generator.
* @throws UnsupportedOperationException
* when replacing an element in the list is not supported.
*/
public static void shuffle(List> list, Random random) {
@SuppressWarnings("unchecked") // we won't put foreign objects in
final List objectList = (List) list;
if (list instanceof RandomAccess) {
for (int i = objectList.size() - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
objectList.set(index, objectList.set(i, objectList.get(index)));
}
} else {
Object[] array = objectList.toArray();
for (int i = array.length - 1; i > 0; i--) {
int index = random.nextInt(i + 1);
Object temp = array[i];
array[i] = array[index];
array[index] = temp;
}
int i = 0;
ListIterator it = objectList.listIterator();
while (it.hasNext()) {
it.next();
it.set(array[i++]);
}
}
}
/**
* Returns a set containing the specified element. The set cannot be
* modified. The set is serializable.
*
* @param object
* the element.
* @return a set containing the element.
*/
public static Set singleton(E object) {
return new SingletonSet(object);
}
/**
* Returns a list containing the specified element. The list cannot be
* modified. The list is serializable.
*
* @param object
* the element.
* @return a list containing the element.
*/
public static List singletonList(E object) {
return new SingletonList(object);
}
/**
* Returns a Map containing the specified key and value. The map cannot be
* modified. The map is serializable.
*
* @param key
* the key.
* @param value
* the value.
* @return a Map containing the key and value.
*/
public static Map singletonMap(K key, V value) {
return new SingletonMap(key, value);
}
/**
* Sorts the given list in ascending natural order. The algorithm is
* stable which means equal elements don't get reordered.
*
* @throws ClassCastException if any element does not implement {@code Comparable},
* or if {@code compareTo} throws for any pair of elements.
*/
@SuppressWarnings("unchecked")
public static > void sort(List list) {
Object[] array = list.toArray();
Arrays.sort(array);
int i = 0;
ListIterator it = list.listIterator();
while (it.hasNext()) {
it.next();
it.set((T) array[i++]);
}
}
/**
* Sorts the given list using the given comparator. The algorithm is
* stable which means equal elements don't get reordered.
*
* @throws ClassCastException if any element does not implement {@code Comparable},
* or if {@code compareTo} throws for any pair of elements.
*/
@SuppressWarnings("unchecked")
public static void sort(List list, Comparator super T> comparator) {
T[] array = list.toArray((T[]) new Object[list.size()]);
Arrays.sort(array, comparator);
int i = 0;
ListIterator it = list.listIterator();
while (it.hasNext()) {
it.next();
it.set(array[i++]);
}
}
/**
* Swaps the elements of list {@code list} at indices {@code index1} and
* {@code index2}.
*
* @param list
* the list to manipulate.
* @param index1
* position of the first element to swap with the element in
* index2.
* @param index2
* position of the other element.
*
* @throws IndexOutOfBoundsException
* if index1 or index2 is out of range of this list.
* @since 1.4
*/
@SuppressWarnings("unchecked")
public static void swap(List> list, int index1, int index2) {
if (list == null) {
throw new NullPointerException("list == null");
}
final int size = list.size();
if (index1 < 0 || index1 >= size || index2 < 0 || index2 >= size) {
throw new IndexOutOfBoundsException();
}
if (index1 == index2) {
return;
}
List rawList = (List) list;
rawList.set(index2, rawList.set(index1, rawList.get(index2)));
}
/**
* Replaces all occurrences of Object {@code obj} in {@code list} with
* {@code newObj}. If the {@code obj} is {@code null}, then all
* occurrences of {@code null} are replaced with {@code newObj}.
*
* @param list
* the list to modify.
* @param obj
* the object to find and replace occurrences of.
* @param obj2
* the object to replace all occurrences of {@code obj} in
* {@code list}.
* @return true, if at least one occurrence of {@code obj} has been found in
* {@code list}.
* @throws UnsupportedOperationException
* if the list does not support setting elements.
*/
public static boolean replaceAll(List list, T obj, T obj2) {
int index;
boolean found = false;
while ((index = list.indexOf(obj)) > -1) {
found = true;
list.set(index, obj2);
}
return found;
}
/**
* Rotates the elements in {@code list} by the distance {@code dist}
*
* e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
* calling rotate(list, 3) or rotate(list, -7) would modify the list to look
* like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
*
* @param lst
* the list whose elements are to be rotated.
* @param dist
* is the distance the list is rotated. This can be any valid
* integer. Negative values rotate the list backwards.
*/
@SuppressWarnings("unchecked")
public static void rotate(List> lst, int dist) {
List list = (List) lst;
int size = list.size();
// Can't sensibly rotate an empty collection
if (size == 0) {
return;
}
// normalize the distance
int normdist;
if (dist > 0) {
normdist = dist % size;
} else {
normdist = size - ((dist % size) * (-1));
}
if (normdist == 0 || normdist == size) {
return;
}
if (list instanceof RandomAccess) {
// make sure each element gets juggled
// with the element in the position it is supposed to go to
Object temp = list.get(0);
int index = 0, beginIndex = 0;
for (int i = 0; i < size; i++) {
index = (index + normdist) % size;
temp = list.set(index, temp);
if (index == beginIndex) {
index = ++beginIndex;
temp = list.get(beginIndex);
}
}
} else {
int divideIndex = (size - normdist) % size;
List sublist1 = list.subList(0, divideIndex);
List sublist2 = list.subList(divideIndex, size);
reverse(sublist1);
reverse(sublist2);
reverse(list);
}
}
/**
* Searches the {@code list} for {@code sublist} and returns the beginning
* index of the first occurrence.
*
* -1 is returned if the {@code sublist} does not exist in {@code list}.
*
* @param list
* the List to search {@code sublist} in.
* @param sublist
* the List to search in {@code list}.
* @return the beginning index of the first occurrence of {@code sublist} in
* {@code list}, or -1.
*/
public static int indexOfSubList(List> list, List> sublist) {
int size = list.size();
int sublistSize = sublist.size();
if (sublistSize > size) {
return -1;
}
if (sublistSize == 0) {
return 0;
}
// find the first element of sublist in the list to get a head start
Object firstObj = sublist.get(0);
int index = list.indexOf(firstObj);
if (index == -1) {
return -1;
}
while (index < size && (size - index >= sublistSize)) {
ListIterator> listIt = list.listIterator(index);
if ((firstObj == null) ? listIt.next() == null : firstObj
.equals(listIt.next())) {
// iterate through the elements in sublist to see
// if they are included in the same order in the list
ListIterator> sublistIt = sublist.listIterator(1);
boolean difFound = false;
while (sublistIt.hasNext()) {
Object element = sublistIt.next();
if (!listIt.hasNext()) {
return -1;
}
if ((element == null) ? listIt.next() != null : !element
.equals(listIt.next())) {
difFound = true;
break;
}
}
// All elements of sublist are found in main list
// starting from index.
if (!difFound) {
return index;
}
}
// This was not the sequence we were looking for,
// continue search for the firstObj in main list
// at the position after index.
index++;
}
return -1;
}
/**
* Searches the {@code list} for {@code sublist} and returns the beginning
* index of the last occurrence.
*
* -1 is returned if the {@code sublist} does not exist in {@code list}.
*
* @param list
* the list to search {@code sublist} in.
* @param sublist
* the list to search in {@code list}.
* @return the beginning index of the last occurrence of {@code sublist} in
* {@code list}, or -1.
*/
public static int lastIndexOfSubList(List> list, List> sublist) {
int sublistSize = sublist.size();
int size = list.size();
if (sublistSize > size) {
return -1;
}
if (sublistSize == 0) {
return size;
}
// find the last element of sublist in the list to get a head start
Object lastObj = sublist.get(sublistSize - 1);
int index = list.lastIndexOf(lastObj);
while ((index > -1) && (index + 1 >= sublistSize)) {
ListIterator> listIt = list.listIterator(index + 1);
if ((lastObj == null) ? listIt.previous() == null : lastObj
.equals(listIt.previous())) {
// iterate through the elements in sublist to see
// if they are included in the same order in the list
ListIterator> sublistIt = sublist
.listIterator(sublistSize - 1);
boolean difFound = false;
while (sublistIt.hasPrevious()) {
Object element = sublistIt.previous();
if (!listIt.hasPrevious()) {
return -1;
}
if ((element == null) ? listIt.previous() != null
: !element.equals(listIt.previous())) {
difFound = true;
break;
}
}
// All elements of sublist are found in main list
// starting from listIt.nextIndex().
if (!difFound) {
return listIt.nextIndex();
}
}
// This was not the sequence we were looking for,
// continue search for the lastObj in main list
// at the position before index.
index--;
}
return -1;
}
/**
* Returns an {@code ArrayList} with all the elements in the {@code
* enumeration}. The elements in the returned {@code ArrayList} are in the
* same order as in the {@code enumeration}.
*
* @param enumeration
* the source {@link Enumeration}.
* @return an {@code ArrayList} from {@code enumeration}.
*/
public static ArrayList list(Enumeration enumeration) {
ArrayList list = new ArrayList();
while (enumeration.hasMoreElements()) {
list.add(enumeration.nextElement());
}
return list;
}
/**
* Returns a wrapper on the specified collection which synchronizes all
* access to the collection.
*
* @param collection
* the Collection to wrap in a synchronized collection.
* @return a synchronized Collection.
*/
public static Collection synchronizedCollection(
Collection collection) {
if (collection == null) {
throw new NullPointerException("collection == null");
}
return new SynchronizedCollection(collection);
}
/**
* Returns a wrapper on the specified List which synchronizes all access to
* the List.
*
* @param list
* the List to wrap in a synchronized list.
* @return a synchronized List.
*/
public static List synchronizedList(List list) {
if (list == null) {
throw new NullPointerException("list == null");
}
if (list instanceof RandomAccess) {
return new SynchronizedRandomAccessList(list);
}
return new SynchronizedList(list);
}
/**
* Returns a wrapper on the specified map which synchronizes all access to
* the map.
*
* @param map
* the map to wrap in a synchronized map.
* @return a synchronized Map.
*/
public static Map synchronizedMap(Map map) {
if (map == null) {
throw new NullPointerException("map == null");
}
return new SynchronizedMap(map);
}
/**
* Returns a wrapper on the specified set which synchronizes all access to
* the set.
*
* @param set
* the set to wrap in a synchronized set.
* @return a synchronized set.
*/
public static Set