文章目录
在JDK8中,Java的集合类是一个非常重要的部分,它们提供了丰富的数据结构来存储和操作对象。这些集合类主要位于
java.util
包中,并由两大接口派生而来:一个是
Collection
接口,主要用于存放单一元素;另一个是
Map
接口,主要用于存放键值对。下面是对一些常见集合类的底层实现及源码的简要解析:
一、Collection接口及其子接口
1. List接口
List接口是一个有序的集合,可以包含重复的元素。List接口的实现类主要有ArrayList
、LinkedList
和Vector
。
-
ArrayList
-
底层实现:ArrayList底层维护了一个Object类型的数组(
elementData
),用于存储集合中的元素。// 源码 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // *** transient Object[] elementData; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { }; //*** public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } // *** }
-
扩容机制:当向ArrayList中添加元素时,如果当前数组容量不足,会进行扩容。扩容后的新容量通常是当前容量的1.5倍(向下取整)。如果使用的是无参构造器,则初始容量为0(懒汉式,只有第一次
add
元素时才会进行容量的指定),第一次添加元素时扩容为10。如果使用的是指定大小的构造器,则初始容量为指定大小,后续扩容时按照1.5倍的规则进行。// 调用 public class DemoUtils { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); } } // ArrayList源码 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // *** public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity) { // 容量判断 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private static final int DEFAULT_CAPACITY = 10; // 默认容量10 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 数组最大容量 private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); // >>1表示“除2取整”,因为转为二进制后右移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; } // *** }
-
源码解析:ArrayList的
add
方法会先调用ensureCapacityInternal
方法确保当前容量足够,如果不够则调用grow
方法进行扩容。扩容时会创建一个新的数组,并将旧数组中的元素复制到新数组中。
-
-
LinkedList
-
底层实现:LinkedList底层采用了双向链表结构,每个节点(Node对象)包含三个属性:prev(指向前一个节点)、next(指向后一个节点)和item(存储节点值)。
// 源码 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable { transient int size = 0; /** * Pointer to first node. * Invariant: (first == null && last == null) || * (first.prev == null && first.item != null) */ transient Node<E> first; /** * Pointer to last node. * Invariant: (first == null && last == null) || * (last.next == null && last.item != null) */ transient Node<E> last; public LinkedList() { } public LinkedList(Collection<? extends E> c) { this(); addAll(c); } public boolean add(E e) { // 新增元素 linkLast(e); return true; } /** * Links e as last element. */ 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++; } // 节点类 private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } // *** }
-
特点:LinkedList适合进行频繁的插入和删除操作,因为链表结构可以使得这些操作的时间复杂度为O(1)。但是,LinkedList的查询效率较低,因为需要从头节点开始遍历链表。
-
-
Vector
-
底层实现:Vector的底层实现与ArrayList类似,也是采用了一个Object类型的数组来存储元素。
// 调用 public class DemoUtils { public static void main(String[] args) { // 默认午餐构造(初始默认容量为10) Vector<String> vector = new Vector<>(); vector.add("1");// 1 末尾添加元素,不考虑线程安全 vector.add(0, "2");// 2 在指定下标index设置元素,线程安全 System.out.println(vector.get(0)); // 指定初始容量7,扩容时增量长度为5 Vector<String> vector2 = new Vector<>(7, 5); } } // 源码 public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { protected Object[] elementData;// 元素内容数组 // 有参构造-参数:容量
-