• java中的集合


    ====================================================================================

    1.8中的HashMap

    HashMap    数组+单向链表+红黑树 

    特点:无序 ,线程不安全

    为什么是无序的,往hashmap中添加元素时,是将key hash之后能均匀的分布在hash表中

    key和value都可以是null

    capacity   默认是16  (哈希表的长度)

    loadFactor  默认0.75 (负荷因子)

    threshold = 容量*负荷因子 (临界值)

    size  实际存放的元素个数  (map存放的元素个数)

    哈希表长度

    当传入容量时,传入5 ,设置为8 。即会设置capacity为大于传入值的最小的2的幂次方

    扩容

    当 size  >   capacity * loadFactor   时候,会扩容,新的容量为旧的值的2倍

    本例中,capacity为4,loadFactor为0.75,threshold为3,当添加第4个元素时,会扩容。

     链表转成红黑树,当桶的长度(桶可以理解为哈希表的某一行)大于8并且哈希表的长度大于64时候,会把该桶中节点转为红黑树

     

    ===============================================================================================

    1.8中的ConcurrentHashMap

     数组+单向链表+红黑树

    特点:无序,线程安全

    无序:和HashMap是同样的原因

    以put元素为例子,根据put的元素的key计算出(两次,防止hash冲突)hash值,如果计算出来的要插入的哈希表的行的首节点不存在,则采用CAS无锁的方式添加。如果不是首节点,则采用synchronized对行首节点加锁synchronized后,再进行put操作。

    get元素时不加锁,因为val属性用volatile修饰了,一个线程修改对另外的线程是可见的。

    key和value都不能为null

    1.8与1.7的变化是,1.8中删除了segments,加锁的粒度更细。加入了红黑树这种数据结构。效率更高。

    ================================================================================================

    1.7中的ConcurrentHashMap

    数组+单向链表

    ConcurrentHashMap采用了分段锁的机制,默认的并发级别是16,即segments数组大小是16。对segments数组的操作是采用Unsafe类的,可以保证线程安全。由于Segment是继承了reentrantLock的,对Segment中的HashEntry进行操作时加的是重入锁可以保证线程安全。

    ================================================================================================

    Hashtable   数组+单向链表

    特点:无序,线程安全

    无序:和HashMap是同样的原因

    线程安全:对每个方法进行同步,synchronized

    capacity   默认是11  (哈希表的长度)

    loadFactor  默认0.75 (负荷因子)

    threshold   (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1)

    count   存放的元素个数

    key和value都不能为null

    *********************************************************************************************************************************************

    ConcurrentHashMap 和 Hashtable key和value都不能为null

    value不能为null的原因

    The main reason that nulls aren’t allowed in ConcurrentMaps
    (ConcurrentHashMaps, ConcurrentSkipListMaps) is that
    ambiguities that may be just barely tolerable in non-concurrent
    maps can’t be accommodated. The main one is that if
    map.get(key) returns null, you can’t detect whether the
    key explicitly maps to null vs the key isn’t mapped.
    In a non-concurrent map, you can check this via map.contains(key),
    but in a concurrent one, the map might have changed between calls

    无法分辨是key没找到的null还是有key值为null,这在多线程里面是模糊不清的,主要是在调用get方法时,这个值有可能被其他线程修改了。所以压根就不允许val值为null。key值也不能为null. 在put方法时,会先算出key的hash值,null就抛出异常。而hashmap就不存在上面的情况,并且假如key为null时,会将null的hash值设置为默认的0。

    ***************************************************************************************************************************************************

    HashMap 的遍历  , hashmap提供了迭代器三种遍历方式 ,遍历的方式是外层是哈表表的行,内层是哈希表的每一行中链表或者红黑树

    =================================================================================================

    LinkedHashMap   数组+双向链表+红黑树

    特点:有序,线程不安全

    LinkedHashMap 是HashMap的子类,继承HashMap,重写了父类的节点类型,每个节点持有当前节点的上一个节点的引用和下一个节点的引用。并增加了head和tail属性。

    LinkedHashMap 与HashMap不同的地方是他要维持entry之间的顺序关系。

    key和value都可以是null

    有序:按照访问顺序或者按照元素插入的顺序,根据构造方法acccessOrder值来确定, 默认是元素的插入顺序

    插入顺序指的是:遍历顺序和放入的顺序是一样的

    访问顺序指的是:最后访问的元素总是最后遍历出来

    注意利用head和tail节点,可以实现LRU(最近最少使用淘汰)算法。LRU的核心思想是如果数据最近被访问过,那么将来被访问的几率也很高。

    采用迭代器遍历时候用到了head头节点

    ==================================================================================================

    TreeMap   红黑树

    特点:有序,线程不安全

    有序:一种情况是根据字典顺序排序(即key的compareTo方法,Integer,String都实现了Comparable接口),一种情况是根据传入的比较器进行排序

    当向TreeMap中添加entry时,是根据插入entry的key 来比较排序的,根据比较的大小来决定将entry插入到哪个位置。

    下面的例子中是按照key的字典顺序排序的,所以遍历时候,是从小到大的顺序

    key不可以是null,要用到key的compare方法比较大小

    ==================================================================================================

     ArrayList    动态数组实现

    线程不安全

    插入删除效率低,随机访问效率高

    默认的长度为10

    数组扩容的比例为1.5,即扩容后新数组长度是旧数组长度的1.5倍

    =================================================================================================

    LinkedList    双向链表实现

    线程不安全

    插入删除效率高,随机访问效率低

    与ArrayList不同的是,他实现了queue接口,可以当成队列使用

    采用双向链表比用单向链表的好处是:查找时,我们可以借用二分法的思路,这样双链表的效率可以提高一倍

    缺点是:从存储结构来看,每个双链表的节点要比单链表的节点多一个指针,浪费空间了

    =================================================================================================

    CopyOnWriteArrayList    动态数组+重入锁

    线程安全是由于是哟和了重去锁

    与ArrayList的比较

        //线程不安全
        static List list= new  ArrayList<Integer>();
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = () -> {
                for (int i = 0; i < 10000; i++) {
                    list.add(i);
                }    
            };
            Thread one = new Thread(runnable);
            Thread two = new Thread(runnable);
            one.start();
            two.start();
            one.join();
            two.join();
            System.out.println(list.size());
        }
    //线程安全
        // static CopyOnWriteArrayList<Integer> list= new CopyOnWriteArrayList<Integer>();
         static List<Integer> list = Collections.synchronizedList(new  ArrayList<Integer>());
        //线程不安全
        //static List list= new  ArrayList<Integer>();
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable = () -> {
                for (int i = 0; i < 10000; i++) {
                    list.add(i);
                }    
            };
            Thread one = new Thread(runnable);
            Thread two = new Thread(runnable);
            one.start();
            two.start();
            one.join();
            two.join();
            System.out.println(list.size());
        }

    ================================================================================================

    HashSet       对HashMap的封装

    元素不能重复

    线程不安全

    无序

    =================================================================================================

    LinkedHashSet    继承了HashSet,对LinkedHashMap的封装

    元素不能重复

    线程不安全

    有序(只能按照插入顺序遍历)

    =================================================================================================

  • 相关阅读:
    macOS 常用配置
    maven 常用配置
    log4j(1.x)最全配置!!!
    Python2 中 input() 和 raw_input() 的区别
    用 Maven 构建 Java-Scala 混合项目
    trim() 的秘密
    【目录】一起来学 Kafka 吧
    Spring in Action.4th
    Hibernate快速入门
    html2canvas 跨域图片无法正常加载问题解决办法
  • 原文地址:https://www.cnblogs.com/moris5013/p/10718800.html
Copyright © 2020-2023  润新知