java集合底层详解

2025-04-13 18

Java集合底层详解

开头解决方案

Java集合框架是Java编程中非常重要的组成部分,它提供了一系列的接口和实现类来存储和操作对象。深入探讨Java集合的底层实现原理,包括ArrayListLinkedListHashMap等常用集合类的内部结构和运作机制。通过,读者可以更清楚地理解这些集合类在内存中的表现形式以及它们的操作方式。

为了解决常见的性能问题和优化需求,我们将从以下几个方面进行分析:
1. 数据结构的选择及其对性能的影响。
2. 集合类的扩容机制。
3. 线程安全问题及解决方案。

接下来,我们将分别针对不同类型的集合进行详细分析,并提供代码示例。

1. ArrayList底层详解

1.1 数据结构

ArrayList基于动态数组实现,支持快速随机访问。其底层是一个Object数组。

java
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8683452581122892189L;</p>

<pre><code>// 默认初始容量
private static final int DEFAULT_CAPACITY = 10;

// 存储元素的数组
transient Object[] elementData;

// 当前存储的元素个数
private int size;

}

1.2 扩容机制

当向ArrayList添加元素时,如果当前容量不足以容纳新元素,会触发扩容操作。扩容过程如下:

java
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为原容量的1.5倍
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 将旧数组复制到新数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}

2. LinkedList底层详解

2.1 数据结构

LinkedList基于双向链表实现,适合频繁的插入和删除操作。

java
public class LinkedList extends AbstractSequentialList
        implements List, Deque, Cloneable, java.io.Serializable {</p>

<pre><code>// 节点内部类
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;
    }
}

// 头节点
transient Node<E> first;

// 尾节点
transient Node<E> last;

// 元素个数
transient int size = 0;

}

3. HashMap底层详解

3.1 数据结构

HashMap基于哈希表实现,提供了键值对的存储和快速查找功能。

java
public class HashMap extends AbstractMap
        implements Map, Cloneable, Serializable {</p>

<pre><code>// 默认初始容量
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16

// 容量
static final int MAXIMUM_CAPACITY = 1 << 30;

// 默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;

// 存储键值对的数组
transient Node<K,V>[] table;

// 键值对的内部类
static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()       { return value; }
    public final String toString() { return key+"="+value; }
    public final int hashCode()    { return Objects.hashCode(key) ^ Objects.hashCode(value); }
    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }
}

}

3.2 扩容机制

HashMap中的元素数量超过阈值(即capacity * load factor)时,会触发扩容操作。扩容过程如下:

java
void resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}

4.

通过以上分析,我们可以看到ArrayListLinkedListHashMap各有其独特的数据结构和操作机制。选择合适的集合类型对于程序的性能至关重要。例如,在需要频繁插入和删除的场景下,LinkedList可能更为合适;而在需要快速查找的场景下,HashMap则更为高效。

了解集合类的扩容机制可以帮助我们更好地控制内存使用,避免不必要的性能开销。在多线程环境下,还需要考虑线程安全问题,可以选择使用同步集合类如Collections.synchronizedListConcurrentHashMap等。

Image// 来源:https://www.nzw6.com

1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!cheeksyu@vip.qq.com
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或教程,您可以投稿发布,成功分享后有积分奖励和额外收入!
5.严禁将资源用于任何违法犯罪行为,不得违反国家法律,否则责任自负,一切法律责任与本站无关

源码下载