博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDK源码解读(1)ArrayList和LinkedList
阅读量:7030 次
发布时间:2019-06-28

本文共 4313 字,大约阅读时间需要 14 分钟。

hot3.png

上学时学过ArrayList底层采用数组实现,LinkedList底层基于链表实现。ArrayList读取效率高,LinkedList增删改效率高。

下面我们看看具体的实现:

ArrayList

ArrayList中有个Object的elementData数组用来承载数据,transient标识该字段不需要被序列化。

/** * 空ArrayList的elementData会赋值成一个空的Object数组{} * 当添加第一个元素的时候该数组会扩容默认的容量10 */transient Object[] elementData; // non-private to simplify nested class access

添加对象时:

public boolean add(E e) {    ensureCapacityInternal(size + 1);  // Increments modCount!!    elementData[size++] = e;    return true;}private void ensureCapacityInternal(int minCapacity) {	// 空数组时,默认容量为10    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {    modCount++;    // 如果容量不足时    if (minCapacity - elementData.length > 0)        grow(minCapacity);}/** * 数组的最大值,超过之后将会抛出OutOfMemoryError */private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;private void grow(int minCapacity) {    // overflow-conscious code    int oldCapacity = elementData.length;    // 每次扩容为数组的原长度的一半,故优化时可先初始化数组的长度可提高效率和降低内存占用    int newCapacity = oldCapacity + (oldCapacity >> 1);    if (newCapacity - minCapacity < 0)        newCapacity = minCapacity;    if (newCapacity - MAX_ARRAY_SIZE > 0)        newCapacity = hugeCapacity(minCapacity);    // minCapacity is usually close to size, so this is a win:    elementData = Arrays.copyOf(elementData, newCapacity);}private static int hugeCapacity(int minCapacity) {    if (minCapacity < 0) // overflow        throw new OutOfMemoryError();    return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;}

remove对象

/** * 每次remove的时候都会去遍历一遍elementData */public boolean remove(Object o) {    if (o == null) {        for (int index = 0; index < size; index++)            if (elementData[index] == null) {                fastRemove(index);                return true;            }    } else {        for (int index = 0; index < size; index++)            if (o.equals(elementData[index])) {                fastRemove(index);                return true;            }    }    return false;}private void fastRemove(int index) {    modCount++;    int numMoved = size - index - 1;    if (numMoved > 0)        // 将elementData的尾部copy到elementData中        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    elementData[--size] = null; // clear to let GC do its work}

System中的arraycopy

/** * native关键字说明其修饰的方法是一个原生方法 * @param      src      源数组。 * @param      srcPos   源数组起始位置 * @param      dest     目标数组 * @param      destPos  目标数据起始位置 * @param      length   复制的数量 */public static native void arraycopy(Object src,  int  srcPos,                                        Object dest, int destPos,                                        int length);

LinkedList

LinkedList没有初始容量一说,他的数据结构如下:

/** * Pointer to first node. * Invariant: (first == null && last == null) || *            (first.prev == null && first.item != null) */transient Node
first;/** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */transient Node
last;

node的结构如下:

private static class Node
{ E item; Node
next; Node
prev; Node(Node
prev, E element, Node
next) { this.item = element; this.next = next; this.prev = prev; }}

linkFirst、linkLast

/** * Links e as first element. */private void linkFirst(E e) {    final Node
f = first; final Node
newNode = new Node<>(null, e, f); first = newNode; if (f == null) last = newNode; else f.prev = newNode; size++; modCount++;}/** * Links e as last element. */void linkLast(E e) { final Node
l = last; final Node
newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++;}

注意:在LinkedList存储第一个Node节点的时候,first和last同时指向该node,然后分别向2端扩展。

HashSet

private transient HashMap
map;

HashSet中采用一个HashMap来承载数据,由于大家对HashMap都比较熟悉,这里不多说。

转载于:https://my.oschina.net/qq596392912/blog/654839

你可能感兴趣的文章
封装了些文件相关的操作
查看>>
什么是Solr
查看>>
poj2386(简单dfs)
查看>>
双链表的基本操作
查看>>
走进异步编程的世界 - 剖析异步方法(上)
查看>>
[HAOI2006]受欢迎的牛
查看>>
docker-maven-plugin 完全免Dockerfile 文件
查看>>
day20 Python 装饰器
查看>>
限制性与非限制性定语从句区别
查看>>
fiddler工具的使用
查看>>
jquery源码分析(二)——架构设计
查看>>
javascript深入理解js闭包(转)
查看>>
207. Course Schedule
查看>>
如何优化您的 Android 应用 (Go 版)
查看>>
Trie树实现
查看>>
Opencv无法调用cvCaptureFromCAM无法打开电脑自带摄像头
查看>>
Exception异常处理机制
查看>>
复杂的web---web中B/S网络架构
查看>>
编写文档的时候各种问题
查看>>
Eclipse里maven的project报Unbound classpath variable: 'M2_REPO/**/***/***.jar
查看>>