arraylist,linklist的部分源码介绍和一些区别
Posted 温一壶月光当茶饮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了arraylist,linklist的部分源码介绍和一些区别相关的知识,希望对你有一定的参考价值。
arraylist:
3个构造器:
(1)默认构造器(使用这个构造器初始化的集合容量为默认初始化容量10)
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
(2)自定义容量的构造器(如果初始化是传入的列表初始容量>0则正常创建传入的容量的集合,如果传入的列表初始容量为0,则创建一个用于空实例的共享数组实例,其他情况时抛出异常)
private static final int DEFAULT_CAPACITY = 10;// 默认初始化容量
private static final Object[] EMPTY_ELEMENTDATA = {};//用于空实例的共享空数组实例。
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
(3)传入一个集合作为参数的构造器(传入的集合转为数组,如果数组的长度!=0,并且数据的类的类对象不是Object类对象则调用Arrays.copyOf()方法初始化,如果数组长度为0 则创建一个空实例)
public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
方法
1 add方法(先检查容量是否足够,如果不够则扩容,如果容量足够就把要加入的数据放在原来数据的末尾,并且加容量+1)
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
每次扩容后容量为之前的1.5倍,再将数据复制到新扩容的集合里
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); }
2 get 方法 (先进行范围检查,如果所查的索引不再集合的容量区间里则抛出越界异常,如果所查索引没有超出范围,则正常返回所查索引对应的值)
public E get(int index) { rangeCheck(index); return elementData(index); } private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
3 remove 方法
(如果remove的参数是一个对象 则先判定这个对象是否==null,如果为空则找到值为空的索引,在根据下面介绍的fastRemove(int index)方法将其删除,如果传入的对象不为空,则先找到所删除的值在集合中的下标,在用fastRemove(int index)方法将其删除
如果remove的参数是一个索引值,则先判定索引值是否在集合的容量区间内,再求得要移动的次数,然后删除该元素
)
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; } 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; }
根据索引将集合中的元素删除,首先求得删除该元素需要移动的次数,如果移动的次数>0则调用arraycopy()方法获得新的集合,将原始的集合的最后一项置为空
private void fastRemove(int index) { modCount++; 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 }
linklist
构造器
1 默认构造器(无参数)
public LinkedList() { }
2 传入一个集合的构造器
public LinkedList(Collection<? extends E> c) { this(); addAll(c); }
方法
1 add方法(在已存在的的节点末尾加上该节点即可实现增加)
public boolean add(E e) { linkLast(e); return true; } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
2 remove方法(将要删除的节点的前一个节点指向要删除的节点的下一个节点即可实现节点的删除)
public boolean remove(Object o) { if (o == null) { for (Node<E> x = first; x != null; x = x.next) { if (x.item == null) { unlink(x); return true; } } } else { for (Node<E> x = first; x != null; x = x.next) { if (o.equals(x.item)) { unlink(x); return true; } } } return false; } E unlink(Node<E> x) { // assert x != null; final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next; x.prev = null; } if (next == null) { last = prev; } else { next.prev = prev; x.next = null; } x.item = null; size--; modCount++; return element; }
ArrayList与LinkedList的区别
ArrayList基于数组实现,因此具有: 有序、元素可重复、插入慢、 索引快 这些数组的特性; (查询快,增删慢)
LinkedList 基于双向链表实现, 因此具有链表 插入快、 索引慢的特性;(增删快,查询慢)
以上是关于arraylist,linklist的部分源码介绍和一些区别的主要内容,如果未能解决你的问题,请参考以下文章