zoukankan      html  css  js  c++  java
  • 源码分析之Collection

     

    Collection

      Collection是List、Queue和Set的超集,它直接继承于Iterable,也就是所有的Collection集合类都支持for-each循环。

    public interface Collection<E> extends Iterable<E> {
        //返回集合的长度,如果长度大于Integer.MAX_VALUE,返回 //返回集合的长度,如果长度大于Integer.MAX_VALUE,返回Integer.MAX_VALUE
        int size();
    
        //如果集合元素总数为0,返回true
        boolean isEmpty();
    
        //判断集合中是否包含指定的元素,其依据是equals()方法
        boolean contains(Object o);
    
        //返回一个包含集合中所有元素的数组
        Object[] toArray();
    
        //与上个类似,只是增加了类型的转换
        <T> T[] toArray(T[] a);
    
        //向集合中加入一个元素,如果成功加入则返回true,如果加入失败,或者因集合本身已经包含同个元素而不再加入时,返回false
        boolean add(E e);
    
        //从集合中删除指定元素的单个实例
        boolean remove(Object o);
    
        //如果集合包含指定集合中的所有元素,返回true
        boolean containsAll(Collection<?> c);
    
        //把指定集合中的所有元素添加到集合中,但在此期间,如果指定的集合发生了改变,可能出现意想不到的事情
        boolean addAll(Collection<? extends E> c);
    
        //从集合中删除所有包含在指定集合中的元素
        boolean removeAll(Collection<?> c);
    
        //仅保留集合中包含在指定集合中的元素
        boolean retainAll(Collection<?> c);
    
        //清空集合
        void clear();
    
        //将此方法抽象,是保证所有子类都覆写此方法,以保证equals的正确行为
        boolean equals(Object o);
    
        //同上
        int hashCode();
    
        //这个方法在JDK1.8中提供了默认的实现,会使用Iterator的形式删除符合条件的元素
        default boolean removeIf(Predicate<? super E> filter){
            Objects.requireNonNull(filter);
            boolean removed = false;
            final Iterator<E> each = iterator();
            while (each.hasNext()) {
                if (filter.test(each.next())) {
                    each.remove();
                    removed = true;
                }
            }
            return removed;
        }
    }
    View Code

    Collections

      Collections 是一个操作 Set、List 和 Map 等集合的工具类。Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法。

      Collections 类中提供了多个 synchronizedXXX() 方法,该方法可使指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

    static <T> Set<T> synchronizedSet(Set<T> s) {
         return new SynchronizedSet<>(s);
    } 

      Collections提供了三类方法返回一个不可变集合:

    emptyXXX() :返回一个空的只读集合
    singleXXX():返回一个只包含指定对象,只有一个元素,只读的集合。
    unmodifiablleXXX():返回指定集合对象的只读视图。

      Collections提供了sort方法对集合进行排序:

    public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。默认是升序
    public static <T> void sort(List<T> list,Comparator<? super T> ):将集合中元素按照指定规则排序。

     

    Comparator源码解析

    示例:compare()结果小于0,顺序反转

    class TimSort<T> {
        /**
         *
         * @param a the array to be sorted
         * @param lo the index of the first element, inclusive, to be sorted
         * @param hi the index of the last element, exclusive, to be sorted
         * @param c the comparator to use
         * @param work a workspace array (slice)  默认null
         * @param workBase origin of usable space in work array  默认0
         * @param workLen usable size of work array  默认0
         * @since 1.8
         */
        static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c, T[] work, int workBase, int workLen) {
            assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
            int nRemaining  = hi - lo;
            if (nRemaining < 2)
                return;  // Arrays of size 0 and 1 are always sorted
            // If array is small, do a "mini-TimSort" with no merges.  MIN_MERGE = 32
            if (nRemaining < MIN_MERGE) { 
                int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
                binarySort(a, lo, hi, lo + initRunLen, c);
                return;
            }
            /**
             * March over the array once, left to right, finding natural runs,extending short natural runs to minRun elements, and merging runs to maintain stack invariant.
             */
            TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
            int minRun = minRunLength(nRemaining);
            do {
                // Identify next run
                int runLen = countRunAndMakeAscending(a, lo, hi, c);
                // If run is short, extend to min(minRun, nRemaining)
                if (runLen < minRun) {
                    int force = nRemaining <= minRun ? nRemaining : minRun;
                    binarySort(a, lo, lo + force, lo + runLen, c);
                    runLen = force;
                }
                // Push run onto pending-run stack, and maybe merge
                ts.pushRun(lo, runLen);
                ts.mergeCollapse();
    
                // Advance to find next run
                lo += runLen;
                nRemaining -= runLen;
            } while (nRemaining != 0);
            // Merge all remaining runs to complete sort
            assert lo == hi;
            ts.mergeForceCollapse();
            assert ts.stackSize == 1;
        }
    
        /**
         * Returns the length of the run beginning at the specified position in the specified array and reverses the run if it is descending (ensuring that the run will always be     * ascending when the method returns).对集合从第0位开始进行检查,如果在第p位出现前后顺序不一致(例如1,5,3),则停止检查,并返回p。如果第0位至第p位中compare(o1,o2)<0,则进行冒泡反转排序。确保结果升序
         *
         * A run is the longest ascending sequence with: a[lo] <= a[lo + 1] <= a[lo + 2] <= ...
         * or the longest descending sequence with: a[lo] >  a[lo + 1] >  a[lo + 2] >  ...
         *
         * For its intended use in a stable mergesort, the strictness of the definition of "descending" is needed so that the call can safely
         * reverse a descending sequence without violating stability.
         *
         * @param a the array in which a run is to be counted and possibly reversed
         * @param lo index of the first element in the run
         * @param hi index after the last element that may be contained in the run.
                  It is required that {@code lo < hi}.
         * @param c the comparator to used for the sort
         * @return  the length of the run beginning at the specified position in the specified array
         */
        private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi, Comparator<? super T> c) {
            assert lo < hi;
            int runHi = lo + 1;
            if (runHi == hi)
                return 1;
    
            // Find end of run, and reverse range if descending 
            if (c.compare(a[runHi++], a[lo]) < 0) { // Descending 可以看到compare的第一个参数是集合中后面的数据,第二个参数是集合中前面的数
                while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
                    runHi++;
                reverseRange(a, lo, runHi);
            } else {                              // Ascending
                while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
                    runHi++;
            }
            return runHi - lo;
        }
    
        /**
         * Reverse the specified range of the specified array. 冒泡排序
         *
         * @param a the array in which a range is to be reversed
         * @param lo the index of the first element in the range to be reversed
         * @param hi the index after the last element in the range to be reversed
         */
        private static void reverseRange(Object[] a, int lo, int hi) {
            hi--;
            while (lo < hi) {
                Object t = a[lo];
                a[lo++] = a[hi];
                a[hi--] = t;
            }
        }
    
    
    /**
         * Sorts the specified portion of the specified array using a binary insertion sort.  This is the best method for sorting small numbers of elements.       * It requires O(n log n) compares, but O(n^2) data movement (worst case).
         * If the initial part of the specified range is already sorted, this method can take advantage of it: the method assumes that the
         * elements from index {@code lo}, inclusive, to {@code start}, exclusive are already sorted.
         *
         * @param a the array in which a range is to be sorted
         * @param lo the index of the first element in the range to be sorted
         * @param hi the index after the last element in the range to be sorted
         * @param start the index of the first element in the range that is
         *        not already known to be sorted ({@code lo <= start <= hi})
         * @param c comparator to used for the sort
         */
        @SuppressWarnings("fallthrough")
        private static <T> void binarySort(T[] a, int lo, int hi, int start,Comparator<? super T> c) {
            assert lo <= start && start <= hi;
            if (start == lo)
                start++;
            for ( ; start < hi; start++) {
                T pivot = a[start];
                // Set left (and right) to the index where a[start] (pivot) belongs
                int left = lo;
                int right = start;
                assert left <= right;
                /*
                 * Invariants:
                 *   pivot >= all in [lo, left).
                 *   pivot <  all in [right, start).
                 */
                while (left < right) {
                    int mid = (left + right) >>> 1;
                    if (c.compare(pivot, a[mid]) < 0)
                        right = mid;
                    else
                        left = mid + 1;
                }
                assert left == right;
    
                /*
                 * The invariants still hold: pivot >= all in [lo, left) and pivot < all in [left, start), so pivot belongs at left.  Note
                 * that if there are elements equal to pivot, left points to the first slot after them -- that's why this sort is stable.
                 * Slide elements over to make room for pivot.
                 */
                int n = start - left;  // The number of elements to move
                // Switch is just an optimization for arraycopy in default case
                switch (n) {
                    case 2:  a[left + 2] = a[left + 1];
                    case 1:  a[left + 1] = a[left];
                             break;
                    default: System.arraycopy(a, left, a, left + 1, n);
                }
                a[left] = pivot;
            }
        }
    
    }
    View Code
  • 相关阅读:
    初识现代软件工程——构建之法
    个人作业3——个人总结(Alpha阶段)
    结对编程2
    个人作业2——英语学习APP案例分析
    结对作业1
    java四则运算
    个人附加作业
    个人作业3——个人总结(Alpha阶段)
    结对编程2——单元测试
    个人作业2——英语学习APP案例分析
  • 原文地址:https://www.cnblogs.com/ryjJava/p/14308340.html
Copyright © 2011-2022 走看看