繁体   English   中英

Java所有集合背后使用的数据结构

[英]data structures used behind all the collections in java

最近,面试官问我要提供java中所有集合(例如ArrayList,Map等)背后的数据结构时,我对此感到困惑。这些数据结构本身不是吗? 如果没有,那么哪些数据结构支持它们?

ArrayList的基础数据结构是Array,LinkedList是Link对象,HashMap是LinkedList或Tree的数组。 希望这可以帮助。

由于源代码提供了所有实现细节,因此,我将仅展示一堆最常用的collections


  • java.util.ArrayList<E>

ArrayList的实现内部回退到Object array

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
 */
transient Object[] elementData; // non-private to simplify nested class access

由于arrays具有固定大小,因此在每次add调用时, ArrayList都会通过对System::arrayCopy本地调用重新创建elementData (如有必要)。


  • java.util.LinkedList<E>

LinkedList的作用是对象引用而不是array 所有项E都存储在内部class Node<E>实例中:

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;
    }
}

每个Node都有一个指向其下一个和上一个兄弟Node的指针。

LinkedList仅保留对其第一个和最后一个元素的引用,不支持ergo随机访问:

/**
 * 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;

  • java.util.HashMap<K,V>

它们将键和值存储到内部捆绑包类Node<K,V> extends Map.Entry<K,V>

通过函数调用HashMap::putVal将节点存储到Node array

/**
 * The table, initialized on first use, and resized as
 * necessary. When allocated, length is always a power of two.
 * (We also tolerate length zero in some operations to allow
 * bootstrapping mechanics that are currently not needed.)
 */
transient Node<K,V>[] table;

另外, Hashmap使用EntrySet extends AbstractSet<Map.Entry<K,V>>集合,该集合不断反映table的元素。

/**
 * Holds cached entrySet(). Note that AbstractMap fields are used
 * for keySet() and values().
 */
transient Set<Map.Entry<K,V>> entrySet;

然后, entrySet作为可迭代collection公开:

for ( Map.Entry<String, Integer> entry : this.myMap.entrySet() ) { /* ... */ }

  • java.util.HashSet<E>

有趣的是HashSet<T>使用HashMap<T, Object> ,正如我们所见,它再次由java.util.Set<T>支持。

private transient HashMap<E,Object> map;

与其他java数据结构的主体相比,您会看到HashSet的主体受到限制,因为其大多数操作只是其内部HashMap结构的后备。

例如:

HashSet::add

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

HashSet::iterator

public Iterator<E> iterator() {
    return map.keySet().iterator();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM