黑马程序员技术交流社区

标题: 【上海校区】Java篇 - Collections的使用和实现 [打印本页]

作者: 不二晨    时间: 2019-2-15 09:40
标题: 【上海校区】Java篇 - Collections的使用和实现
目录:

Collections的sort
Collections的search
Collections的reverse
Collections的shuffle
Collections的swap
Collections的fill
Collections的copy
Collections的min和max
Collections的rotate
Collections的Unmodifiable
Collections的Synchronized




1. Collections的sort

对集合元素进行排序。



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[]),内部实现是:

在jdk1.7之后,Arrays类中的sort方法有一个分支判断,当LegacyMergeSort.userRequested为true的情况下,采用legacyMergeSort,否则采用ComparableTimSort。并且在legacyMergeSort的注释上标明了该方法会在以后的jdk版本中废弃,因此以后Arrays类中的sort方法将采用ComparableTimSort类中的sort方法。

具体可以看我的上一篇文章:《Java篇 - Arrays的使用和实现》https://blog.csdn.net/u014294681/article/details/86265920





2. Collections的search

对集合进行查找,和数组一样,查找使用的是二分查找,也可以传入外比较器,待查找的集合需要本身有序,否则查找出来的下标将不准。



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));
    }
执行输出:

[0, 0, 0, 3, 4, 6, 7, 7, 10, 10, 11, 11, 11, 14, 16, 16, 17, 18, 18, 19]
search 10 index = 9


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()));
    }
执行输出:

origin = [6, 2, 14, 11, 16, 15, 15, 7, 15, 2, 0, 7, 16, 12, 16, 7, 15, 2, 6, 17]
reverse = [17, 6, 2, 15, 7, 16, 12, 16, 7, 0, 2, 15, 7, 15, 15, 16, 11, 14, 2, 6]



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()));
    }
执行输出:

origin = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
shuffle = [2, 15, 6, 14, 18, 5, 17, 16, 1, 3, 9, 7, 11, 13, 8, 4, 12, 10, 19, 0]



4.2 实现原理

    private static Random r;
    private static final int SHUFFLE_THRESHOLD        =    5;

    public static void shuffle(List<?> list) {
        Random rnd = r;
        if (rnd == null)
            r = rnd = new Random();
        shuffle(list, rnd);
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    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();

            for (int i=size; i>1; i--)
                swap(arr, i-1, rnd.nextInt(i));
            ListIterator it = list.listIterator();
            for (int i=0; i<arr.length; i++) {
                it.next();
                it.set(arr);
            }
        }
    }
第一步,判断Random是否已经实例化(懒加载),如果没有,则构造一个随机对象。
第二步,判断集合大小是否小于SHUFFLE_THRESHOLD或者集合为随机访问类型,如果是,则调用swap函数随机交换集合元素,如果不是则走第三步。
第三步,将集合转换成数组,然后随机交换数组元素。
第四步,将打乱好的数组重新赋值给集合。




5. Collections的swap

将集合中两个位置的元素进行交换。



5.1 使用
    private static void testSwap() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add(i);
        }
        System.out.println("origin = " + Arrays.toString(list.toArray()));
        Collections.swap(list, 1, 10);
        System.out.println("swap = " + Arrays.toString(list.toArray()));
    }
执行输出:

origin = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
swap = [0, 10, 2, 3, 4, 5, 6, 7, 8, 9, 1, 11, 12, 13, 14, 15, 16, 17, 18, 19]



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. Collections的fill

将集合的元素全部填充为某个值。



6.1 使用
    private static void testFill() {
        List<Integer> list = new ArrayList<>();
        System.out.println("origin = " + Arrays.toString(list.toArray()));
        Collections.fill(list, 1);
        System.out.println("fill = " + Arrays.toString(list.toArray()));
    }
执行输出:

origin = []
fill = []

这点要注意,集合和数组不一样,数组是初始化之后就会分配一块连续的内容。而集合的实现有很多种,上面用到ArrayList,它重写的Collection的size()方法是它实际存储的元素个数。而Collections fill元素的时候是以这个size作为边界结点来赋值的。

改一下代码:

    private static void testFill() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add(i);
        }
        System.out.println("origin = " + Arrays.toString(list.toArray()));
        Collections.fill(list, 1);
        System.out.println("fill = " + Arrays.toString(list.toArray()));
    }
执行输出:
origin = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
fill = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]



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")。

执行输出:

source = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
origin dest = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
dest dest = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]



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. Collections的rotate

对集合进行旋转,rotate是将集合旋转一定的distance,分为正方向和反方向旋转,看传入的distance的正负。



9.1 使用
    private static void testRotate() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add(i);
        }
        System.out.println("list = " + Arrays.toString(list.toArray()));
        Collections.rotate(list, -5);
        System.out.println("rotate -5 = " + Arrays.toString(list.toArray()));
        Collections.rotate(list, 5);
        System.out.println("rotate 5 = " + Arrays.toString(list.toArray()));
    }
执行输出:

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
rotate -5 = [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4]
rotate 5 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]




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;

        reverse(list.subList(0, mid));
        reverse(list.subList(mid, size));
        reverse(list);
    }
1. 如果集合size小于ROTATE_THRESHOLD或者集合类型为随机访问类型则进入到rotate1分支,否则进入到rotate2分支。
2. 进入rotate1分支,对于rotate1的实现具体的做法是,将序列的第一个元素交换至正确的位置i,此时原来在位置i的元素就是一个错误放置的元素displaced,然后计算该元素正确放置的位置i,并将其放置到位置i,此时又得到一个错误放置的元素displaced,重复此过程直到错误放置的元素displaced被放置到了第一个位置(即i == 0)。
3. 进入rotate2分支,对于rotate2的实现与上面的实现完全不一样,因为考虑到rotate2适用于的是类似于采用链表存储的List,因此不具有随机访问的特性。因此该实现采用的是将原list在-distance mod size处使用subList方法拆分为两个子列表s1,s2,并分别反转俩链表revese(s1),reverse(s2),最后再将整个链表反转。




10. Collections的Unmodifiable

传入一个集合,生成一个不可修改的集合。



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;

        final List<? extends E> list;

        UnmodifiableList(List<? extends E> list) {
            super(list);
            this.list = list;
        }

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

        private Object readResolve() {
            return (list instanceof RandomAccess
                    ? new UnmodifiableRandomAccessList<>(list)
                    : this);
        }
    }

    static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E>
                                              implements RandomAccess
    {
        UnmodifiableRandomAccessList(List<? extends E> list) {
            super(list);
        }

        public List<E> subList(int fromIndex, int toIndex) {
            return new UnmodifiableRandomAccessList<>(
                list.subList(fromIndex, toIndex));
        }

        private static final long serialVersionUID = -2542308836966382001L;

        private Object writeReplace() {
            return new UnmodifiableList<>(list);
        }
    }
可以看到原理很简单,属于装饰器模式,将一个集合包装成一个不可修改的集合:读方法调用传入集合的读方法,写方法直接抛出异常。





11. Collections的Synchronized

将一个普通集合转换成同步集合,但是不推荐这种方式,因为它的锁粒度很大,属于锁全局,具体的可以看看我之前关于同步并发的文章。



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;

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

        private Object readResolve() {
            return (list instanceof RandomAccess
                    ? new SynchronizedRandomAccessList<>(list)
                    : this);
        }
    }

    static class SynchronizedRandomAccessList<E>
        extends SynchronizedList<E>
        implements RandomAccess {

        SynchronizedRandomAccessList(List<E> list) {
            super(list);
        }

        SynchronizedRandomAccessList(List<E> list, Object mutex) {
            super(list, mutex);
        }

        public List<E> subList(int fromIndex, int toIndex) {
            synchronized (mutex) {
                return new SynchronizedRandomAccessList<>(
                    list.subList(fromIndex, toIndex), mutex);
            }
        }

        private static final long serialVersionUID = 1530674583602358482L;

        private Object writeReplace() {
            return new SynchronizedList<>(list);
        }
    }
可以看到,也是装饰器模式,将一个普通集合的所有方法一股脑用synchronized包装起来。
---------------------
【转载,仅作分享,侵删】
作者:况众文
原文:https://blog.csdn.net/u014294681/article/details/86310680
版权声明:本文为博主原创文章,转载请附上博文链接!


作者: 不二晨    时间: 2019-2-20 09:39
今天也要加油鸭
作者: jojob    时间: 2019-8-26 10:45
这个有点狠




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2