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的区别?
- LinkedHashMap是HashMap的子类。
- 底层是都是散列表,不过HashMap是数组+链表。LinkedHashMap是数组+双向链表。
- put方法几乎完全相同,只不过进行了一些细节上的调整。
- 扩容操作的调整,基于性能和LinkedHashMap自身的考量,重哈希过程(transfer方法)进行了重写。
HashMap与HashSet区别?
- HashMap实现了Map接口,HashSet实现了Set接口
- Map存储K-V,HashSet存储对象(把对象作为key存储,仅仅存储key)
- 调用put()向map中添加元素,调用add()向set中添加元素
- HashMap使用key的HashCode来进行再哈希。HashSet使用成员对象来计算HashCode值,对于两个对象hashCode可能相同,所以使用equals来判断对象向邓姓。
- HashMap比HashSet要快,因为HashMap使用唯一个key获取对象。
- 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
- ArrayList
- LinkedList
- Vector(了解,已过时)
- Set
- HashSet
- LinkedHashSet
- TreeSet
- Map
- HashMap
- LinkedHashMap
- TreeMap
- ConcurrentHashMap
- Hashtable(了解,,已过时)
网友评论