Java Map

 先上一张Java集合的框架图,便于参考

以下所有特性仅代表自JAVA 1.8

Map

public interface Map<K,V> {
    int size();
    boolean containsKey(Object key);
    V put(K key, V value);
    V remove(Object key);
    void clear();
    .
    .
    .
}


 HashMap

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable{

   /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    /**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

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

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
    }

}


        1.Hashmap默认初始化容量为16,负载因子默认0.75
        2.使用 Node<K,V>[] table (数组) 和 Node<K,V>[](单向链表) 来存储数据

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
    }


        3.HashMap将会自动扩容当内存容量大于 (Capacity * loadFactor)时
        4.扩容后的新 Capacity 将会是旧的容量的两倍
        5.使用Key计算出 hashcode, 再转化为在数组 (Node<K,V>[])table中的位置 所以 HashMap是无序的
        6.HashMap没有使用同步机制,所以HashMap是线程不安全的
 

LinkedHashMap

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>{

    /**
     * The head (eldest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> head;

    /**
     * The tail (youngest) of the doubly linked list.
     */
    transient LinkedHashMap.Entry<K,V> tail;

    static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
    }


}

 
        1.默认初始化容量为16,负载因子默认0.75
        2.使用 Entry[16] table  和  Entry<K,V>(双向链表)来存储数据

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;
}


        3.LinkedHashMap将会自动扩容当内存容量超过(Capacity * loadFactor)
        4.新容量Capacity将会是旧的容量的两倍
        5.使用hashcode来计算数据在数组 (Entry[])table中的位置,但是使用双向链表结构来存储数据和记录顺序,所以LinkedHashMap是有序的。
        6.LinkedHashMap没有使用同步机制,所以LinkedHashMap是线程不安全的

TreeMap         TreeMap底层实现原理

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
    private transient Entry<K,V> root;

    static final class Entry<K,V> implements Map.Entry<K,V> {
        K key;
        V value;
        Entry<K,V> left;
        Entry<K,V> right;
        Entry<K,V> parent;
        boolean color = BLACK; //Using the Red-Black Tree
    }


}

        1.TreeMap是按照Key的自然顺序或者Comprator的顺序进行排序,因此TreeMap是有序的

        2.无初始化大小,数据添加不需要扩容

        3.使用红黑树数据结构存储数据

        4.没有使用同步机制或锁,TreeMap是线程不安全的

HashTable

public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

    /**
     * The hash table data.
     */
    private transient Entry<?,?>[] table;

    public Hashtable() {
        this(11, 0.75f);
    }

    /**
     * Hashtable bucket collision list entry
     */
    private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;
    }


    @SuppressWarnings("unchecked")
    public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }

}

        1.基本实现原理和HashMap一致,HashTable通过synchronized同步代码块和 CAS操作来实现线程安全,因此HashTable是线程安全的

        2.默认初始大小11,加载因子0.75,每次扩容为 2n+1

ConcurrentHashMap

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentMap<K,V>, Serializable {

    private static final int DEFAULT_CAPACITY = 16;

    private static final float LOAD_FACTOR = 0.75f;

    transient volatile Node<K,V>[] table;

    /**
     * The next table to use; non-null only while resizing.
     */
    private transient volatile Node<K,V>[] nextTable;

    //jdk1.8中虽然不在使用分段锁,但是仍然有Segment这个类,但是没有实际作用
    static class Segment<K,V> extends ReentrantLock implements Serializable {
        private static final long serialVersionUID = 2249069246763182397L;
        final float loadFactor;
        Segment(float lf) { this.loadFactor = lf; }
    }

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;
    }

}

         1.Node数组使用来存放树或者链表的头结点,当一个链表中的数量到达一个数目时,会使查询速率降低,所以到达一定阈值时,会将一个链表转换为一个红黑二叉树,提升查询的速率。

        2.使用Synchroized关键字来同步代码块,因此ConcurrentHashMap是线程安全的

        3.扩容为原来的两倍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值