美文网首页JAVA
各种集合比较

各种集合比较

作者: 秋笙fine | 来源:发表于2019-02-18 00:14 被阅读93次

    HashMap为什么允许为null?
    首先put的时候,就会对key==null做一个判断,对于key==null的Entry,会调用putForNullKey直接去遍历table[0]上的哈希桶,寻找e.key=null的Entry或者没有找到遍历结束。找到则覆盖原值,没找到就调用addEntry方法添加一个key为null的Entry。

    为什么说HashMap是无序的?(因为其初始化的时候采用的是位哈希算法)
    HashMap在第一次put的时候完成初始化,通过模运算(其实是高或低16位的按位与运算的位哈希算法 使1均匀分布,有利于泊松分布,降低哈希碰撞的概率)来计算哈希槽中的落槽位置即数组下标的(由于我们无法预料按位与的结果,所以这里是无序的)。

    HashMap高并发情况下的问题?改善?
    HashMap高并发情况下的扩容数据丢失以及死链问题。因为hashmap线程不安全,所以如果两个线程同时对同一Entry进行操作,会丢失数据。死链问题:Entry的next被并发修改导致的对象丢失,两个对象互链,对象自己互链的中两个对象互链产生的死锁。改善,1.8Hashmap采用对原先链表的引用,保证有序性,除此之外,可以使用ConcurrentHashmap。1.7使用segement分段锁,1.8使用CAS保证有序,voliate关键字保证可见。

    HashMap存放自定义类的时候,为什么要重写hashCode和equals。
    因为我们要通过hashCode然后模运算(现在是按位与的哈希算法)来计算table中的下标,然后遍历这之后的链表,通过equals比较有没有相同的key,如果有直接覆盖value,因为要通过equals比较有没有相同的key,所以要重写equals,而由于约定并且提高散列表性能,重写equals必须重写hashCode。

    HashMap与Hashtable比较。


    image.png

    上面确认在数组中的索引不同即哈希值的使用不同,hashtable直接使用对象的哈希值求出索引,hashmap则进行取模运算(按位与),再次哈希。

    HashMap要想实现线程安全,需要调用Collections类的静态方法synchronizeMap()实现

    HashMap中的key可以为任意对象或者数据类型吗?
    可以为null,但不能是可变对象,如果是可变对象的话,对象中的属性改变,则对象的HashCode也改变,导致下次无法查找到table下标,引起数据丢失。

    HashMap与ConcurrentHashMap的区别?
    以下是1.7的区别:
    HashMap线程不安全,ConcurrentHashMap线程安全。
    HashMap是fail-fast的,ConcurrentHashMap是fail-safe的。
    ConcurrentHashMap在1.8以前,使用了Segment分段锁。

    HashTable与ConcurrentHashMap的区别?
    hashTable是使用了一把锁锁住了整个对象。效率非常低下,当一个线程访问同步方法的时候,其它线程访问同步方法,可能会进入阻塞或者轮询的状态。
    ConcurrentHashMap则是使用分段锁,当一个线程占用锁访问其中一个数据的时候,其它段的数据也能被其它线程访问。

    LinkedHashMap与HashMap的区别?

    1. LinkedHashMap是HashMap的子类。
    2. 底层是都是散列表,不过HashMap是数组+链表。LinkedHashMap是数组+双向链表。
    3. put方法几乎完全相同,只不过进行了一些细节上的调整。
    4. 扩容操作的调整,基于性能和LinkedHashMap自身的考量,重哈希过程(transfer方法)进行了重写。

    HashMap与HashSet区别?

    1. HashMap实现了Map接口,HashSet实现了Set接口
    2. Map存储K-V,HashSet存储对象(把对象作为key存储,仅仅存储key)
    3. 调用put()向map中添加元素,调用add()向set中添加元素
    4. HashMap使用key的HashCode来进行再哈希。HashSet使用成员对象来计算HashCode值,对于两个对象hashCode可能相同,所以使用equals来判断对象向邓姓。
    5. HashMap比HashSet要快,因为HashMap使用唯一个key获取对象。
    6. HashSet是对HashMap的封装。

    HashSet如果保证集合没有重复元素?
    HashSet底层是对HashMap的封装,将对象作为HashMap的key,一个通用的Object设置位value,因而当对象重复(即对象的equals和hashCode都相同时),我们会将value覆盖,而key不会有任何的改变。这也是为什么Set方法存的对象必须重写Object的equals和hashCode的原因。因为Object是所有类的超类。

    ArrayList和Vector区别?
    同:都是List接口实现子类,并且存储有序(List接口都有序),底层是数组。可以按照位置取出元素,允许重复和null。

    异:同步性:ArrayList不同步,线程不安全,Vector同步,线程安全,但我们弃用,可以使用Collections工具类来构建出同步的ArrayList而不用Vector。
    扩容:ArrayList使用位运算符(JDK1.5) 扩容成1.5倍,Vector则扩容成两倍。

    List和Map的不同?
    存储结构:List存储单列集合,Map存储K-V
    元素重复:List元素可以重复,Map中key不能重复
    是否有序:List有序,Map无序。

    HashSet使用什么方法判断重复元素?
    equals和hashCode。HashSet封装了HashMap
    集合使用put方法完成Entry的放置,hashCode可以用来计算落槽位置,equals方法可以用来判断key是否相等,所以要重写这两个方法。

    ArrayList和LinedList的存储特性?
    ArrayList底层是数组,因为访问速度快。
    LinedList底层是双向链表,增删速度快。

    Collection(所有类集接口的父接口)

    • List
    1. ArrayList
    2. LinkedList
    3. Vector(了解,已过时)
    • Set
    1. HashSet
    2. LinkedHashSet
    3. TreeSet
    • Map
    1. HashMap
    2. LinkedHashMap
    3. TreeMap
    4. ConcurrentHashMap
    5. Hashtable(了解,,已过时)

    相关文章

      网友评论

        本文标题:各种集合比较

        本文链接:https://www.haomeiwen.com/subject/xrcoeqtx.html