JDK,常见数据结构解读

一。情有独钟

  对数据结构情有独钟,打算慢慢把jdk里的实现都读一遍,发现其中的亮点,持续更新。

二。ArrayList

  这应该是我们学习java最早接触的到的数据结构,众所周知,数组在申请了内存之后,无法扩展;而数组队列,是实现了动态扩容的功能,意义上是为动态数组,实际上的数组扩容是不允许在原地址上伸长的,很简单,因为在你申请的数组空间之后,可能存在别的被申请掉的内存;要实现动态数组,必然是新申请一个更大的连续内存空间,并替换到原来的引用中。

  从构造函数,可以清楚看到,elementData,就是这个存储数据的内存地址。

  然后,找到添加的接口,add;在真正赋值之前,会进行grow方法。

  

  可以看到,真正干活的是这个copyof,找到最后,就是这个方法。

  首先这个泛型数组,会先判断一下如果是Object父类,则直接new Object,如果不是则调用Arrays的接口创建,才去新建一个数组,然后就会去拷贝数组到新的数组,并返回这个被拷贝的数组。

    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

  它的get方法,简单判断一下是否大于元素容量,防止内存泄漏的操作。

    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

  它的remove方法,是将这个位置之后的所有元素,前移一个位置,并将最后的元素设置为null。

    public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

  它提供的排序接口,设计的是传入一个比较器,可以自定升序还是降序,最终一个分支使用的是mergeSort。最后还校验了一下modcount,前后是否相等,如果不相等抛出并发异常,有点CAS的思想。

    @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

  

    public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

  长度小于7插入排序,反正是个n平方的排序,

    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

三。PriorityQueue

  优先队列,读作优先写作二叉树,也叫堆(大顶堆,小顶堆)。

  它的实现方法是数组,使用数组做二叉树,每个元素e[i]的孩子为e[2*i+1],e[2*i+2]。

  找到添加元素的方法;比较器为空的时候;它从末尾插入,先找出父亲,如果父节点比自己大,则继续往上,将父节点往下移动,直到找到比它小的位置插入,默认是一个小顶堆。

    public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        modCount++;
        int i = size;
        if (i >= queue.length)
            grow(i + 1);
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
            siftUp(i, e);
        return true;
    }

    private void siftUpComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>) x;
        while (k > 0) {
            int parent = (k - 1) >>> 1;
            Object e = queue[parent];
            if (key.compareTo((E) e) >= 0)
                break;
            queue[k] = e;
            k = parent;
        }
        queue[k] = key;
    }

  弹出操作就是把堆定元素拿走,然后不断往下找合适的往上移。

    public E poll() {
        if (size == 0)
            return null;
        int s = --size;
        modCount++;
        E result = (E) queue[0];
        E x = (E) queue[s];
        queue[s] = null;
        if (s != 0)
            siftDown(0, x);
        return result;
    }
    private void siftDownComparable(int k, E x) {
        Comparable<? super E> key = (Comparable<? super E>)x;
        int half = size >>> 1;        // loop while a non-leaf
        while (k < half) {
            int child = (k << 1) + 1; // assume left child is least
            Object c = queue[child];
            int right = child + 1;
            if (right < size &&
                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
                c = queue[child = right];
            if (key.compareTo((E) c) <= 0)
                break;
            queue[k] = c;
            k = child;
        }
        queue[k] = key;
    }

猜你喜欢

转载自www.cnblogs.com/chentingk/p/10604847.html