xiaobaoqiu Blog

Think More, Code Less

Java Collection

Collections

Collection的工具类

List sort

调用数组的排序,即Arrays.sort,可以自定义Comparator

1
2
3
4
5
6
7
8
9
public static <T extends Comparable<? super T>> void sort(List<T> list) {
    Object[] a = list.toArray();
    Arrays.sort(a);
    ListIterator<T> i = list.listIterator();
    for (int j=0; j<a.length; j++) {
        i.next();
        i.set((T)a[j]);
    }
}

List binarySearch

对于随机访问的List(如ArrayList)及数据量比较小的非随机访问List(小于5000),采用基于下标的binarySearch,其他(比较大的非随机访问List),采用基于iterator的binarySearch

1
2
3
4
5
6
7
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
        //BINARYSEARCH_THRESHOLD = 5000
        if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
            return Collections.indexedBinarySearch(list, key);
        else
            return Collections.iteratorBinarySearch(list, key);
}

基于下标的binarySearch,和数组的binarySearch很相似:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);   //不一定是随机访问的get
        int cmp = midVal.compareTo(key);

        if (cmp < 0)
            low = mid + 1;
        else if (cmp > 0)
            high = mid - 1;
        else
            return mid; // 找到
    }
    return -(low + 1);  // 没找到
}

采用基于iterator的binarySearch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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); //Iterator i开始的第mid个元素
        int cmp = midVal.compareTo(key);

        if (cmp < 0)
            low = mid + 1;
        else if (cmp > 0)
            high = mid - 1;
        else
            return mid;
    }
    return -(low + 1);
}

List reverse

对于随机访问的List(如ArrayList)及数据量比较小的非随机访问List(小于18),采用基于下标的翻转,其他(比较大的非随机访问List),采用基于iterator的翻转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void reverse(List<?> list) {
    int size = list.size();
    //REVERSE_THRESHOLD = 18
    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);
        }
    }
}

List shuffle

List的打乱顺序,需要一个全局的随机数发生器(Random),打乱的逻辑就是将第i个元素和[0, i)之间的随机位置元素交换.对于随机访问List或者大小很小的List(小于5),直接进行交换,对于比较大的非随机访问List,将其转换为数组再进行shuffle过程.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void shuffle(List<?> list, Random rnd) {
    int size = list.size();
    //SHUFFLE_THRESHOLD = 5
    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
        ListIterator it = list.listIterator();
        for (int i=0; i<arr.length; i++) {
            it.next();
            it.set(arr[i]);
        }
    }
}

List fill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static <T> void fill(List<? super T> list, T obj) {
    int size = list.size();
    //FILL_THRESHOLD = 25
    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);
        }
    }
}

List copy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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");
    //COPY_THRESHOLD = 10
    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());
        }
    }
}

Collection min max

List rotate

旋转,可以左旋或者右旋,第二参数为正数表示右旋,负数表示左旋. 如list = [t, a, n, k, s],则Collections.rotate(list, 1)之后变为[s, t, a, n, k]. Collections.rotate(list, 1)等效于Collections.rotate(list, -4)

随机访问或者小于100的非随机访问List,采用循环设置的方法.

比较大的非随机访问List采用三次reverse的方法,在编程珠玑中专门介绍了这种方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public static void rotate(List<?> list, int distance) {
    //ROTATE_THRESHOLD = 100
    if (list instanceof RandomAccess || list.size() < ROTATE_THRESHOLD)
        rotate1((List)list, distance);
    else
        rotate2((List)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;
    //总共肯定只有size次设置
    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;

    reverse(list.subList(0, mid));      //左侧翻转
    reverse(list.subList(mid, size));   //右侧翻转
    reverse(list);                      //全部翻转
}

List replaceAll

List indexOfSubList lastIndexOfSubList

indexOfSubList : target子序列在source序列中第一次出现的位置 lastIndexOfSubList : target子序列在source序列中最后一次出现的位置

unmodifiable系列

指元素不可变更的集合,是对原始集合的一个包装,需要支持原始集合的所有方法. unmodifiableCollection,unmodifiableSet,unmodifiableSortedSet,unmodifiableList等 实现原理都是使用内部类,不支持的操作(如List的add,remove等)直接抛出UnsupportedOperationException异常.

1
2
3
4
5
6
7
8
9
10
11
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                      implements List<E> {
    final List<? extends E> list;
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }
    //其他方法
}

synchronized系列

指保证同步的集合,原理是对原始集合的一个包装,另外加上一个mutex,对原始集合每个方法的操作都会用synchronized(mutex)保证同步. synchronizedCollection,synchronizedSet,synchronizedSortedSet,synchronizedList等.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//注意SynchronizedCollection定义了mutex
tatic class SynchronizedCollection<E> implements Collection<E>, Serializable {
    final Collection<E> c;  // Backing Collection
    final Object mutex;     // Object on which to synchronize
    //...
}
static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
    final List<E> list;
    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);}
    }
    //...
}

checked系列

获取一个集合的保证类型安全的试图,任何一个试图向集合中插入错误类型的元素会抛出ClassCastException异常 实现原理很简单,构造函数需要传入集合及一个类型(Class),每次插入操作是会额外增加一次类型检查的操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static class CheckedCollection<E> implements Collection<E>, Serializable {
    final Collection<E> c;
    final Class<E> type;    //支持的类型
    //类型检查
    void typeCheck(Object o) {
        if (!type.isInstance(o))
            throw new ClassCastException("Attempt to insert " +
               o.getClass() + " element into collection with element type "
               + type);
    }
}

static class CheckedList<E> extends CheckedCollection<E> implements List<E>
{
    final List<E> list;

    public E set(int index, E element) {
        typeCheck(element); //类型检查
        return list.set(index, element);
    }

    public void add(int index, E element) {
        typeCheck(element);
        list.add(index, element);
    }
    //...
}

empty系列

EMPTY_LIST, EMPTY_MAP 对get和contain等获取元素操作重写.

singleton系列

值包含一个元素的聚合 SingletonSet, singletonList, singletonMap等

List nCopies

返回一个包含n个o的List, 用一个类CopiesList实现,特制了get等操作

1
2
public static <T> List<T> nCopies(int n, T o) {
}

Comparator reverseOrder

获取一个比较器的反向比较器,ReverseComparator实现,实现很简单,compare的顺序颠倒一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static class ReverseComparator<T>
    implements Comparator<Comparable<Object>>, Serializable {
    public int compare(Comparable<Object> c1, Comparable<Object> c2) {
        return c2.compareTo(c1);
    }
}
private static class ReverseComparator2<T> implements Comparator<T>,
        Serializable
{
    private Comparator<T> cmp;

    ReverseComparator2(Comparator<T> cmp) {
        assert cmp != null;
        this.cmp = cmp;
    }

    public int compare(T t1, T t2) {
        return cmp.compare(t2, t1); //比较顺序颠倒一下
    }
}

Collection frequency

集合中对象出现的次数,支持对象为null

Collection disjoint

判断两个集合是否无交集,即无相同的元素

Collection addAll

AsLIFOQueue

即返回Deque的一个后进先出(Last-in-first-out, Lifo)的视图.

1
2
3
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
        return new SetFromMap<E>(map);
    }