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);
}
}