/* Copyright (c) 2008-2014, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. There is NO WARRANTY for this software. See license.txt for details. */ package java.util; import avian.Data; public class Collections { private Collections() { } public static void shuffle(List list, Random random) { Object[] array = Data.toArray(list, new Object[list.size()]); for (int i = 0; i < array.length; ++i) { int j = random.nextInt(array.length); Object tmp = array[i]; array[i] = array[j]; array[j] = tmp; } list.clear(); for (int i = 0; i < array.length; ++i) { list.add(array[i]); } } public static void shuffle(List list) { shuffle(list, new Random()); } public static void sort(List list) { sort(list, new Comparator() { public int compare(Object a, Object b) { return ((Comparable) a).compareTo(b); } }); } private final static int SORT_SIZE_THRESHOLD = 16; public static void sort(List list, Comparator comparator) { int size = list.size(); introSort(list, comparator, 0, size, size); insertionSort(list, comparator); } private static void introSort(List list, Comparator comparator, int begin, int end, int limit) { while (end - begin > SORT_SIZE_THRESHOLD) { if (limit == 0) { heapSort(list, comparator, begin, end); return; } limit >>= 1; // median of three T a = list.get(begin); T b = list.get(begin + (end - begin) / 2 + 1); T c = list.get(end - 1); T median; if (comparator.compare(a, b) < 0) { median = comparator.compare(b, c) < 0 ? b : (comparator.compare(a, c) < 0 ? c : a); } else { median = comparator.compare(b, c) > 0 ? b : (comparator.compare(a, c) > 0 ? c : a); } // partition int pivot, i = begin, j = end; for (;;) { while (comparator.compare(list.get(i), median) < 0) { ++i; } --j; while (comparator.compare(median, list.get(j)) < 0) { --j; } if (i >= j) { pivot = i; break; } T swap = list.get(i); list.set(i, list.get(j)); list.set(j, swap); ++i; } introSort(list, comparator, pivot, end, limit); end = pivot; } } private static void heapSort(List list, Comparator comparator, int begin, int end) { int count = end - begin; for (int i = count / 2 - 1; i >= 0; --i) { siftDown(list, comparator, i, count, begin); } for (int i = count - 1; i > 0; --i) { // swap begin and begin + i T swap = list.get(begin + i); list.set(begin + i, list.get(begin)); list.set(begin, swap); siftDown(list, comparator, 0, i, begin); } } private static void siftDown(List list, Comparator comparator, int i, int count, int offset) { T value = list.get(offset + i); while (i < count / 2) { int child = 2 * i + 1; if (child + 1 < count && comparator.compare(list.get(child), list.get(child + 1)) < 0) { ++child; } if (comparator.compare(value, list.get(child)) >= 0) { break; } list.set(offset + i, list.get(offset + child)); i = child; } list.set(offset + i, value); } private static void insertionSort(List list, Comparator comparator) { int size = list.size(); for (int j = 1; j < size; ++j) { T t = list.get(j); int i = j - 1; while (i >= 0 && comparator.compare(list.get(i), t) > 0) { list.set(i + 1, list.get(i)); --i; } list.set(i + 1, t); } } public static int binarySearch(List list, T needle) { int left = -1, right = list.size(); while (left + 1 < right) { int middle = (left + right) >> 1; int result = ((Comparable)needle).compareTo(list.get(middle)); if (result < 0) { right = middle; } else if (result > 0) { left = middle; } else { return middle; } } return -1 - right; } public static void reverse(List list) { int ascending = 0, descending = list.size() - 1; while (ascending < descending) { T tmp = list.get(ascending); list.set(ascending++, list.get(descending)); list.set(descending--, tmp); } } public static final List EMPTY_LIST = new UnmodifiableList(new ArrayList(0)); public static final List emptyList() { return EMPTY_LIST; } public static final Map emptyMap() { return (Map) new UnmodifiableMap( new HashMap(0)); } public static final Set emptySet() { return (Set) new UnmodifiableSet( new HashSet(0)); } public static Enumeration enumeration(Collection c) { return new IteratorEnumeration (c.iterator()); } public static Comparator reverseOrder(Comparator cmp) { return new ReverseComparator(cmp); } static class IteratorEnumeration implements Enumeration { private final Iterator it; public IteratorEnumeration(Iterator it) { this.it = it; } public T nextElement() { return it.next(); } public boolean hasMoreElements() { return it.hasNext(); } } static class SynchronizedCollection implements Collection { protected final Object lock; protected final Collection collection; public SynchronizedCollection(Object lock, Collection collection) { this.lock = lock; this.collection = collection; } public int size() { synchronized (lock) { return collection.size(); } } public boolean isEmpty() { return size() == 0; } public boolean contains(Object e) { synchronized (lock) { return collection.contains(e); } } public boolean add(T e) { synchronized (lock) { return collection.add(e); } } public boolean addAll(Collection collection) { synchronized (lock) { return this.collection.addAll(collection); } } public boolean remove(Object e) { synchronized (lock) { return collection.remove((T)e); } } public Object[] toArray() { return toArray(new Object[size()]); } public T[] toArray(T[] array) { synchronized (lock) { return collection.toArray(array); } } public void clear() { synchronized (lock) { collection.clear(); } } public Iterator iterator() { return new SynchronizedIterator(lock, collection.iterator()); } public boolean containsAll(Collection c) { synchronized (lock) { return collection.containsAll(c); } } public boolean removeAll(Collection c) { synchronized (lock) { return collection.removeAll(c); } } } static class SynchronizedMap implements Map { protected final Object lock; protected final Map map; SynchronizedMap(Map map) { this.map = map; this.lock = this; } SynchronizedMap(Object lock, Map map) { this.lock = lock; this.map = map; } public void clear() { synchronized (lock) { map.clear(); } } public boolean containsKey(Object key) { synchronized (lock) { return map.containsKey(key); } } public boolean containsValue(Object value) { synchronized (lock) { return map.containsValue(value); } } public Set> entrySet() { synchronized (lock) { return new SynchronizedSet>(lock, map.entrySet()); } } public V get(Object key) { synchronized (lock) { return map.get(key); } } public boolean isEmpty() { synchronized (lock) { return map.isEmpty(); } } public Set keySet() { synchronized (lock) { return new SynchronizedSet(lock, map.keySet()); } } public V put(K key, V value) { synchronized (lock) { return map.put(key, value); } } public void putAll(Map elts) { synchronized (lock) { map.putAll(elts); } } public V remove(Object key) { synchronized (lock) { return map.remove(key); } } public int size() { synchronized (lock) { return map.size(); } } public Collection values() { synchronized (lock) { return new SynchronizedCollection(lock, map.values()); } } } public static Map synchronizedMap(Map map) { return new SynchronizedMap (map); } static class SynchronizedSet extends SynchronizedCollection implements Set { public SynchronizedSet(Object lock, Set set) { super(lock, set); } } public static Set synchronizedSet(Set set) { return new SynchronizedSet (set, set); } static class SynchronizedList extends SynchronizedCollection implements List { private final List list; public SynchronizedList(List list) { super(list, list); this.list = list; } @Override public T get(int index) { synchronized (lock) { return list.get(index); } } @Override public T set(int index, T value) { synchronized (lock) { return list.set(index, value); } } @Override public T remove(int index) { synchronized (lock) { return list.remove(index); } } @Override public void add(int index, T element) { synchronized (lock) { list.add(index, element); } } @Override public boolean addAll(int startIndex, Collection c) { synchronized (lock) { return list.addAll(startIndex, c); } } @Override public int indexOf(Object value) { synchronized (lock) { return list.indexOf(value); } } @Override public int lastIndexOf(Object value) { synchronized (lock) { return list.lastIndexOf(value); } } @Override public ListIterator listIterator(int index) { // as described in the javadocs, user should be synchronized on list before calling return list.listIterator(index); } @Override public ListIterator listIterator() { // as described in the javadocs, user should be synchronized on list before calling return list.listIterator(); } } static class RandomAccessSynchronizedList extends SynchronizedList implements RandomAccess { public RandomAccessSynchronizedList(List list) { super(list); } } public static List synchronizedList(List list) { List result; if (list instanceof RandomAccess) { result = new RandomAccessSynchronizedList(list); } else { result = new SynchronizedList(list); } return result; } static class SynchronizedIterator implements Iterator { private final Object lock; private final Iterator it; public SynchronizedIterator(Object lock, Iterator it) { this.lock = lock; this.it = it; } public T next() { synchronized (lock) { return it.next(); } } public boolean hasNext() { synchronized (lock) { return it.hasNext(); } } public void remove() { synchronized (lock) { it.remove(); } } } static class ArrayListIterator implements ListIterator { private final List list; private int toRemove = -1; private int index; public ArrayListIterator(List list) { this(list, 0); } public ArrayListIterator(List list, int index) { this.list = list; this.index = index - 1; } public boolean hasPrevious() { return index >= 0; } public T previous() { if (hasPrevious()) { toRemove = index; return list.get(index--); } else { throw new NoSuchElementException(); } } public T next() { if (hasNext()) { toRemove = ++index; return list.get(index); } else { throw new NoSuchElementException(); } } public boolean hasNext() { return index + 1 < list.size(); } public void remove() { if (toRemove != -1) { list.remove(toRemove); index = toRemove - 1; toRemove = -1; } else { throw new IllegalStateException(); } } } public static List unmodifiableList(List list) { return new UnmodifiableList(list); } static class UnmodifiableList implements List { private List inner; UnmodifiableList(List l) { this.inner = l; } public T get(int index) { return inner.get(index); } public T set(int index, T value) { throw new UnsupportedOperationException(); } public T remove(int index) { throw new UnsupportedOperationException(); } public boolean remove(Object o) { throw new UnsupportedOperationException(); } public boolean add(T element) { throw new UnsupportedOperationException(); } public void add(int index, T element) { throw new UnsupportedOperationException(); } public Iterator iterator() { return new UnmodifiableIterator(inner.iterator()); } public int indexOf(Object value) { return inner.indexOf(value); } public int lastIndexOf(Object value) { return inner.lastIndexOf(value); } public boolean isEmpty() { return inner.isEmpty(); } public ListIterator listIterator(int index) { return new UnmodifiableListIterator(inner.listIterator(index)); } public ListIterator listIterator() { return new UnmodifiableListIterator(inner.listIterator()); } public int size() { return inner.size(); } public boolean contains(Object element) { return inner.contains(element); } public boolean addAll(Collection collection) { throw new UnsupportedOperationException(); } public Object[] toArray() { return inner.toArray(); } public S[] toArray(S[] array) { return inner.toArray(array); } public void clear() { throw new UnsupportedOperationException(); } public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } public boolean addAll(int startIndex, Collection c) { throw new UnsupportedOperationException(); } public boolean containsAll(Collection c) { return inner.containsAll(c); } } public static Map unmodifiableMap(Map m) { return new UnmodifiableMap(m); } static class UnmodifiableMap implements Map { private Map inner; UnmodifiableMap(Map m) { this.inner = m; } public void clear() { throw new UnsupportedOperationException(); } public boolean containsKey(Object key) { return inner.containsKey(key); } public boolean containsValue(Object value) { return inner.containsValue(value); } public Set> entrySet() { return unmodifiableSet(inner.entrySet()); } public V get(Object key) { return inner.get(key); } public boolean isEmpty() { return inner.isEmpty(); } public Set keySet() { return unmodifiableSet(inner.keySet()); } public V put(K key, V value) { throw new UnsupportedOperationException(); } public void putAll(Map t) { throw new UnsupportedOperationException(); } public V remove(Object key) { throw new UnsupportedOperationException(); } public int size() { return inner.size(); } public Collection values() { return unmodifiableCollection(inner.values()); } } static class UnmodifiableIterator implements Iterator { private final Iterator inner; UnmodifiableIterator(Iterator inner) { this.inner = inner; } @Override public T next() { return inner.next(); } @Override public boolean hasNext() { return inner.hasNext(); } @Override public void remove() { throw new UnsupportedOperationException(); } } static class UnmodifiableListIterator extends UnmodifiableIterator implements ListIterator { private final ListIterator innerListIterator; UnmodifiableListIterator(ListIterator listIterator) { super(listIterator); this.innerListIterator = listIterator; } @Override public boolean hasPrevious() { return innerListIterator.hasPrevious(); } @Override public T previous() { return innerListIterator.previous(); } } static class UnmodifiableCollection implements Collection { private final Collection inner; UnmodifiableCollection(Collection inner) { this.inner = inner; } @Override public Iterator iterator() { return new UnmodifiableIterator(inner.iterator()); } @Override public int size() { return inner.size(); } @Override public boolean isEmpty() { return inner.isEmpty(); } @Override public boolean contains(Object element) { return inner.contains(element); } @Override public boolean containsAll(Collection c) { return inner.containsAll(c); } @Override public boolean add(T element) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection collection) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object element) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection c) { throw new UnsupportedOperationException(); } @Override public Object[] toArray() { return inner.toArray(); } @Override public S[] toArray(S[] array) { return inner.toArray(array); } @Override public void clear() { throw new UnsupportedOperationException(); } } public static UnmodifiableCollection unmodifiableCollection(Collection collection) { return new UnmodifiableCollection(collection); } static class UnmodifiableSet extends UnmodifiableCollection implements Set { UnmodifiableSet(Set inner) { super(inner); } } public static Set unmodifiableSet(Set hs) { return new UnmodifiableSet(hs); } private static final class ReverseComparator implements Comparator { Comparator cmp; public ReverseComparator(Comparator cmp) { this.cmp = cmp; } public int compare(T o1, T o2) { return - cmp.compare(o1, o2); } } public static List singletonList(T o) { ArrayList list = new ArrayList(1); list.add(o); return new UnmodifiableList(list); } }