集合框架脑图下载地址【免费】
图片不太清晰的话可以点击上方链接下载
List和Map、Set的区别?
List和Set都是单列数据的集合,Map是存储键和值这样的双列数据集合。
-
List中存储的数据是有顺序的,并且允许重复。
-
Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。
-
Set中存储的数据是无序的,不允许重复,但元素在集合中的位置由hashcode决定,位置是固定的(Set集合根据hashcode来进行数据的存储,所以位置是固定的,但是位置不是用户可以控制的,所以对于用户来说set集合还是无序的)。
HashMap底层原理
HashMap根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,具有很快的访问速度,但是遍历顺序却不确定。
HashMap最多只允许一条记录的键为null,允许多条记录的值为null。
HashMap线程不安全,在同一时刻可以有多个线程同时写HashMap,可能会导致数据不一致。
如果需要满足线程安全,可以使用Collections的synchronizedMap方法使HashMap具有线程安全能力,或者使用ConcurrentHashMap,HashTable。
HashMap是怎样保证数据不重复的?
HashMap通过重写HashCode和equals保证数据不重复。
下面以(对象)为例(对象1,2是相同的,里面的值也一样):
因为当我们向hashmap添加(对象1)时,hashmap首先会调用对象的hashCode来计算hash值作为地址,如果没有重写hashCode方法,那么hashmap是调用的Object的hashCode方法来计算hash值,Object中hashCode计算出来的hash值其实就是对象的地址,(对象1)与(对象2)存储的的地址肯定不同。所以我们无法通过(对象1)找到(对象1)的地址。自然就找不(对象1)的数据
但是当我们重写hashCode以后,他就可以通过重写的HashCode计算出来的hash值找到相同的键的位置,在这之后并不会直接从该地址获取值(HashMap为了解决hash值冲突的问题,使用了拉链法),而是会调用equals方法进行判断,这就和没有重写HashCode造成错误的原因类似了,没有重写equals方法,就要被迫调用Object类的equals方法,而Object类的equals方法是直接比较两个对象的内存地址所以还是找不到。
HashCode的值相同,元素不一定相同。
HashCode的值不同,元素一定不相同。
首先判断HashCode值相同才会调用equals。
拉链法
拉链法就是将数组和链表相结合,也就是说创建一个链表数组,数组中每一个格子都存放着一个链表,如果hash冲突,就会将冲突的值加入到链表中。
Set
HashSet底层是由HashMap时间,不允许集合中有重复的值,使用该方式需要重写hashcode()和equals()。
LinkEdHashSet继承与HashSet,同时又基于LinkedHashMap来实现,底层是LinkedHashMap。
HashSet会通过元素的hashcode()和equals()方法进行判断,当试图将元素加入到Set集合时,HashSet首先会使用对象的hashcode方法来判断对象加入的位置。同时也会与其他已经加入的对象的hashcode进行比较,如果不相等hashcodeHashSet就认为这个对象之前不存在,如果之前存在同样的hashcode值,就会进一步的比较equals()方法,如果equals()比较返回结果是true,那么认为该对象在集合中的对象是一模一样的,不会将其加入;如果比较返回的是false,那么HashSet认为新加入的对象没有重复,可以正确加入。