1、Collections类介绍
文章目录
类Collections以静态方法的方式提供了很多通用算法和功能,这些功能大概分为两类
对容器接口对象进行操作
- 查找和替换
- 排序和调整顺序
- 添加和修改
返回一个容器接口对象
- 适配器:将其他类型的数据转换为容器接口对象
- 装饰器:修饰一个给定容器接口对象,增加某些性质
2、对接口对象的操作
2.1、查找和替换
二分查找
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
//实现了RandomAceess接口,RandomAccess是一个空接口,表明一个特征,在算法实现的时候可以体现
//这里就利用到了
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
//基于索引查找
return Collections.indexedBinarySearch(list, key);
else
//基于迭代器查找
return Collections.iteratorBinarySearch(list, key);
}
//数组的二分查找算法,效率为O(log2N)
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
}
//;链表的二分查找,比较的次数为O(lOg2N),遍历移动的次数为O(N)
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
}
2.2、查找最大值、最小值
实现思路很简单:通过迭代器进行比较
//查找最大值与最小值的方法
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
//通过迭代器进行比较
Iterator<? extends T> i = coll.iterator();
T candidate = i.next();
//遍历Collection接口
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) > 0)
candidate = next;
}
return candidate;
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
if (comp==null)
return (T)max((Collection) coll);
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;
}
2.3、查找元素出现的次数
//返回元素o在容器中出现的次数
//实现思路很简单,就是通过迭代器进行比较
public static int frequency(Collection<?> c, Object o) {
int result = 0;
if (o == null) {
for (Object e : c)
if (e == null)
result++;
} else {
for (Object e : c)
if (o.equals(e))
result++;
}
return result;
}
2.4、查找list出现的位子
//暴力破解:将target列表与source从第一个元素开始的列表逐个元素进行比较
public static int indexOfSubList(List<?> source, List<?> target) {
int sourceSize = source.size();
int targetSize = target.size();
int maxCandidate = sourceSize - targetSize;
if (sourceSize < INDEXOFSUBLIST_THRESHOLD ||
(source instanceof RandomAccess&&target instanceof RandomAccess)) {
nextCand:
//将
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
for (int i=0, j=candidate; i<targetSize; i++, j++)
if (!eq(target.get(i), source.get(j)))
continue nextCand; // Element mismatch, try next cand
return candidate; // All elements of candidate matched target
}
} else { // Iterator version of above algorithm
ListIterator<?> si = source.listIterator();
nextCand:
for (int candidate = 0; candidate <= maxCandidate; candidate++) {
ListIterator<?> ti = target.listIterator();
for (int i=0; i<targetSize; i++) {
if (!eq(ti.next(), si.next())) {
// Back up source iterator to next candidate
for (int j=0; j<i; j++)
si.previous();
continue nextCand;
}
}
return candidate;
}
}
return -1; // No candidate matched the target
}
2.5、排序
@SuppressWarnings("unchecked")
//排序,内部通过Arrays.sort实现
public static <T extends Comparable<? super T>> void sort(List<T> list) {
//先将List元素复制到一个数组中
Object[] a = list.toArray();
//使用Arrays.sort进行排序
Arrays.sort(a);
ListIterator<T> i = list.listIterator();
//排序后,再复制回list
for (int j=0; j<a.length; j++) {
i.next();
i.set((T)a[j]);
}
}
2.6、交换位置
//交换第i和第j个元素的内容
@SuppressWarnings({"rawtypes", "unchecked"})
public static void swap(List<?> list, int i, int j) {
// 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)));
}
2.7、反转列表
//反转列表的顺序
@SuppressWarnings({"rawtypes", "unchecked"})
public static void reverse(List<?> list) {
int size = list.size();
//实现思路:
//将第一个和最后一个交换,第二个和倒数第二个交换,以此类推,直到中间两个元素交换完毕
//如果实现了RandomAccess接口或列表比较大小。根据索引位置使用swap方法进行交换
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定位待交换的元素
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);
}
}
}
2.8、随机化重排
//随机化重排
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
//随机化重排
//从后往前遍历列表,逐个给每个位置重新赋值,值从前面的末尾重新赋值的元素随机挑选
//如果列表实现了RandomAceess接口,或者列表比较小,直接使用前面的swap方法进行交换
//否则,先将列表内容复制到一个数组中,洗牌,再复制回列表
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();
// 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<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
3、返回一个容器接口对象
3.1、适配器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9w61kth0-1582875105378)(images/39.png)]
3.1.1、空容器的方法
返回一个静态不可变对象,可以节省创建新对象内存和时间开销
public static <T> Iterator<T> emptyIterator() {
return (Iterator<T>) EmptyIterator.EMPTY_ITERATOR;
}
private static class EmptyIterator<E> implements Iterator<E> {
public static <T> ListIterator<T> emptyListIterator() {
public static final <T> Set<T> emptySet() {
return (Set<T>) EMPTY_SET;
}
3.1.2、单一对象方法
将一个对象转还为一个标准的容器接口对象
public static <T> Set<T> singleton(T o) {
return new SingletonSet<>(o);
}
public static <T> List<T> singletonList(T o) {
return new SingletonList<>(o);
}
3.2、装饰器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61KEWmbX-1582875105379)(images/40.png)]
3.2.1、写安全
生成Collection内部的静态类,所有写方法会抛出异常
public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c) {
return new UnmodifiableCollection<>(c);
}
static class UnmodifiableCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 1820017752578914078L;
final 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> T[] toArray(T[] a) {return c.toArray(a);}
public String toString() {return c.toString();}
public Iterator<E> iterator() {
return new Iterator<E>() {
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();
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
// Use backing collection version
i.forEachRemaining(action);
}
};
}
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
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 void clear() {
throw new UnsupportedOperationException();
}
// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> action) {
c.forEach(action);
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override
public Spliterator<E> spliterator() {
return (Spliterator<E>)c.spliterator();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> stream() {
return (Stream<E>)c.stream();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> parallelStream() {
return (Stream<E>)c.parallelStream();
}
}
3.2.2、类型安全
public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
return new CheckedSet<>(s, type);
}
/**
* @serial include
*/
static class CheckedSet<E> extends CheckedCollection<E>
implements Set<E>, Serializable
{
private static final long serialVersionUID = 4694047833775013803L;
CheckedSet(Set<E> s, Class<E> elementType) { super(s, elementType); }
public boolean equals(Object o) { return o == this || c.equals(o); }
public int hashCode() { return c.hashCode(); }
}
3。2.3、线程安全
这些方法都是通过给所有容器方法加锁来实现的。
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
//注意所有方法都加锁了
/**
* @serial include
*/
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
SynchronizedList(List<E> list) {
super(list);
this.list = list;
}
SynchronizedList(List<E> list, Object mutex) {
super(list, mutex);
this.list = list;
}
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);}
}
/**
* SynchronizedRandomAccessList instances are serialized as
* SynchronizedList instances to allow them to be deserialized
* in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
* This method inverts the transformation. As a beneficial
* side-effect, it also grafts the RandomAccess marker onto
* SynchronizedList instances that were serialized in pre-1.4 JREs.
*
* Note: Unfortunately, SynchronizedRandomAccessList instances
* serialized in 1.4.1 and deserialized in 1.4 will become
* SynchronizedList instances, as this method was missing in 1.4.
*/
private Object readResolve() {
return (list instanceof RandomAccess
? new SynchronizedRandomAccessList<>(list)
: this);
}
}