1.1 使用
private static void testSort() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
Collections.sort(list);
System.out.println(Arrays.toString(list.toArray()));
}
执行输出:[0, 0, 1, 3, 3, 3, 4, 6, 7, 8, 8, 10, 10, 10, 12, 14, 14, 17, 19, 19],默认是按照升序排列的。
我们可以传入一个外比较器:
private static void testSortComparator() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
System.out.println(Arrays.toString(list.toArray()));
}
执行输出:[19, 19, 19, 18, 16, 16, 15, 14, 14, 13, 13, 12, 12, 10, 8, 8, 8, 7, 7, 2],这样就实现了倒序排列。
1.2 实现原理
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
第一步,先将集合转换成数组。
第二步,对数组做排序。
第三步,再重新将数组的值赋给集合。
对数组排序的过程使用的是Arrays.sort(Object[]),内部实现是:
2.1 使用
private static void testSearch() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
System.out.println(Arrays.toString(list.toArray()));
System.out.println("search 10 index = " + Collections.binarySearch(list, 10));
}
此时,集合是无序的,这时查找输出:
[8, 6, 4, 18, 10, 19, 18, 13, 19, 0, 12, 6, 11, 1, 17, 10, 8, 3, 18, 18]
search 10 index = -13
我们先对集合排序再查找:
private static void testSearch() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
Collections.sort(list);
System.out.println(Arrays.toString(list.toArray()));
System.out.println("search 10 index = " + Collections.binarySearch(list, 10));
}
执行输出:
2.2 实现原理
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
private static <T>
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);
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 <T>
int iteratorBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int low = 0;
int high = list.size()-1;
ListIterator<? extends Comparable<? super T>> i = list.listIterator();
while (low <= high) {
int mid = (low + high) >>> 1;
Comparable<? super T> midVal = get(i, 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
}
可以看到,就是二分查找的实现,这边就不再赘述,上一篇文章中有分析。
3. Collections的reverse
对集合数据进行反转。
3.1 使用
private static void testReverse() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
System.out.println("origin = " + Arrays.toString(list.toArray()));
Collections.reverse(list);
System.out.println("reverse = " + Arrays.toString(list.toArray()));
}
执行输出:
3.2 实现原理
private static final int REVERSE_THRESHOLD = 18;
@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<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
@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)));
}
第一步,判断集合大小是否小于REVERSE_THRESHOLD或者集合为随机访问类型,如果是,则从左右以中间位置为基准做交换,如果不是则走第二步。
第二步,用两个迭代器,一个正序,一个倒序,从开始位置到中间位置,用两个迭代器互相交换值。
4. Collections的shuffle
shuffle的意思是洗牌,打乱,顾名思义,就是把集合元素打乱。
4.1 使用
private static void testShuffle() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
System.out.println("origin = " + Arrays.toString(list.toArray()));
Collections.shuffle(list);
System.out.println("shuffle = " + Arrays.toString(list.toArray()));
}
执行输出:
5.2 实现原理
@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)));
}
原理很简单,不赘述了。
6.2 实现原理
private static final int FILL_THRESHOLD = 25;
public static <T> void fill(List<? super T> list, T obj) {
int size = list.size();
if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
for (int i=0; i<size; i++)
list.set(i, obj);
} else {
ListIterator<? super T> itr = list.listIterator();
for (int i=0; i<size; i++) {
itr.next();
itr.set(obj);
}
}
}
第一步,判断集合的size是否小于FILL_THRESHOLD或者集合为随机访问类型,如果是,则遍历集合进行赋值,如果不是则走第二步。
第二步,获取集合迭代器,然后遍历集合用迭代器进行赋值。
7. Collections的copy
将一个集合的元素拷贝到另一个集合。
7.1 使用
private static void testCopy() {
List<Integer> source = new ArrayList<>();
for (int i = 0; i < 20; i++) {
source.add(i);
}
System.out.println("source = " + Arrays.toString(source.toArray()));
int size = source.size();
List<Integer> dest = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
dest.add(1);
}
System.out.println("origin dest = " + Arrays.toString(dest.toArray()));
Collections.copy(dest, source);
System.out.println("dest dest = " + Arrays.toString(dest.toArray()));
}
注意,目标集合的size不能小于源集合的size(这边是ArrayList,size为实际存储元素的个数),否则会报IndexOutOfBoundsException("Source does not fit in dest")。
7.2 实现原理
private static final int COPY_THRESHOLD = 10;
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
第一步,边界校验,目标集合的size必须大于源集合的size,否则抛出异常。
第二步, 判断源集合的size是否小于COPY_THRESHOLD或者源集合与目标集合都为随机访问类型,如果是,则直接循环设置。如果不是,则走第三步。
第三步,拿到源集合和目标集合的迭代器,然后用迭代器遍历设置元素。
8. Collections的min和max
获取集合中元素的最小值或最大值。
8.1 使用
private static void testMinOrMax() {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 20; i++) {
list.add(random.nextInt(20));
}
System.out.println("list = " + Arrays.toString(list.toArray()));
System.out.println("min = " + Collections.min(list));
System.out.println("max = " + Collections.max(list));
}
可以看到,我这边的集合元素是随机生成的,集合中的元素并不是排好序的。
执行输出:
list = [15, 5, 0, 14, 8, 1, 8, 15, 10, 18, 7, 19, 12, 16, 4, 9, 3, 16, 19, 6]
min = 0
max = 19
8.2 实现原理
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll) {
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;
}
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
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;
}
上面代码很明显,就是遍历集合,找出最大或最小值。
9.2 实现原理
private static final int ROTATE_THRESHOLD = 100;
public static void rotate(List<?> list, int distance) {
if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
rotate1(list, distance);
else
rotate2(list, distance);
}
private static <T> void rotate1(List<T> list, int distance) {
int size = list.size();
if (size == 0)
return;
distance = distance % size;
if (distance < 0)
distance += size;
if (distance == 0)
return;
for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) {
T displaced = list.get(cycleStart);
int i = cycleStart;
do {
i += distance;
if (i >= size)
i -= size;
displaced = list.set(i, displaced);
nMoved ++;
} while (i != cycleStart);
}
}
private static void rotate2(List<?> list, int distance) {
int size = list.size();
if (size == 0)
return;
int mid = -distance % size;
if (mid < 0)
mid += size;
if (mid == 0)
return;
10.1 使用
private static void testUnmodifiable() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
List<Integer> result = Collections.unmodifiableList(list);
result.remove(0);
}
执行抛出:Exception in thread "main" java.lang.UnsupportedOperationException
除了Collections.unmodifiableList,还有如下这些相似的方法:
public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
public static <T> Set<T> unmodifiableSet(Set<? extends T> s)
public static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
public static <T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s)
public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m)
public static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m)
public static <K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
10.2 实现原理
以Collections.unmodifiableList(list)为例:
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
implements List<E> {
private static final long serialVersionUID = -283967356065247728L;
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 void add(int index, E element) {
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<E> operator) {
throw new UnsupportedOperationException();
}
@Override
public void sort(Comparator<? super E> c) {
throw new UnsupportedOperationException();
}
public ListIterator<E> listIterator() {return listIterator(0);}
public ListIterator<E> listIterator(final int index) {
return new ListIterator<E>() {
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 void remove() {
throw new UnsupportedOperationException();
}
public void set(E e) {
throw new UnsupportedOperationException();
}
public void add(E e) {
throw new UnsupportedOperationException();
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
i.forEachRemaining(action);
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
return new UnmodifiableList<>(list.subList(fromIndex, toIndex));
}
11.1 使用
private static void testSynchronized() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(i);
}
list = Collections.synchronizedList(list);
}
这样,该集合就能在多线程下保持读写安全了。
除了Collections.synchronizedList(list),还有如下这些相似的方法:
public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T> Set<T> synchronizedSet(Set<T> s)
public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
public static <T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s)
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)
public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
public static <K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m)
11.2 实现原理
以Collections.synchronizedList(list)为例:
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
public boolean equals(Object o) {
if (this == o)
return true;
synchronized (mutex) {return list.equals(o);}
}
public int hashCode() {
synchronized (mutex) {return list.hashCode();}
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
public E set(int index, E element) {
synchronized (mutex) {return list.set(index, element);}
}
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
public E remove(int index) {
synchronized (mutex) {return list.remove(index);}
}
public int indexOf(Object o) {
synchronized (mutex) {return list.indexOf(o);}
}
public int lastIndexOf(Object o) {
synchronized (mutex) {return list.lastIndexOf(o);}
}
public boolean addAll(int index, Collection<? extends E> c) {
synchronized (mutex) {return list.addAll(index, c);}
}
public ListIterator<E> listIterator() {
return list.listIterator(); // Must be manually synched by user
}
public ListIterator<E> listIterator(int index) {
return list.listIterator(index); // Must be manually synched by user
}
public List<E> subList(int fromIndex, int toIndex) {
synchronized (mutex) {
return new SynchronizedList<>(list.subList(fromIndex, toIndex),
mutex);
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
synchronized (mutex) {list.replaceAll(operator);}
}
@Override
public void sort(Comparator<? super E> c) {
synchronized (mutex) {list.sort(c);}
}