盘点Java中List、Set、Map实现类以及他们之间的区别

没有进行扩展,方便复习。需要更详细的,可以访问我的博客查看其它文章

在这里插入图片描述

一、List

存放是有序的,允许存放重复元素

1.1 ArrayList

ArrayList 是常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数 组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数 组的数据复制到新的存储空间中。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进 行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除

1.2 LinkedList

LinkedList是用双向链表结构存储数据的,很适合数据的动态插入和删除随机访问和遍历速度比较 慢。另外,他实现了Deque接口,可以用于操作表头和表尾元素,可以当作堆 栈、队列和双向队列使用。

1.3 Vector

Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一 个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此, 访问它比访问ArrayList慢

二、Set

Set是没有顺序,且不可重复的。判断是否是相同对象是通过对比对象hashCode值(java是依据对象的内存地址计算出的此序号)判断 的,如果想要让两个不同的对象视为相等的,就必须覆盖Object的hashCode方法和equals方法。

在这里插入图片描述

2.1 HashSet(哈希表)

**Set不允许重复,底层是HashMap,无容量限制,是非线程安全的。**虽然底层是HashMap但不存储键值对,值存储对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k950Ow01-1590396561161)(https://gitee.com/hofe/graph/raw/master/img/20200525121559.png)]

HashSet根据元素的哈希值来决定存储在哪个位置,哈希值相同的使用equals判断是否是同一元素,是的话插入操作失败,不是的话就在相同的哈希值下顺延

HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不 同) 而是按照哈希值来存的所以取数据也是按照哈希值取得。

元素的哈希值是通过元素的 hashcode方法来获取的, HashSet首先判断两个元素的哈希值,如果哈希值一样,接着会比较 equals方法 如果 equls结果为true ,HashSet就视为同一个元素。如果equals 为false就不是 同一个元素。 哈希值相同equals为false的元素在同样的哈希值下顺延.

2.2 TreeSet

基于TreeMap实现,支持排序,是非线程安全的

TreeSet()是使用二叉树的原理对新add()的对象按照指定的顺序排序(升序、降序),每增 加一个对象都会进行排序,将对象插入的二叉树指定的位置。
Integer和String对象都可以进行默认的TreeSet排序,而自定义类的对象是不可以的,自 己定义的类必须实现Comparable接口,并且覆写相应的compareTo()函数,才可以正常使 用。
在覆写compare()函数时,要返回相应的值才能使TreeSet按照一定的规则来排序
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整 数、零或正整数

2.3 LinkHashSet

LinkHashSet(HashSet+LinkHashMap),继承自HashSet,底层是LinkedHashMap。这样做的好处是LinkHashSet中的元素顺序是可以保证的,也就是遍历序和插入序是一样的。
对于 LinkedHashSet 而言,它继承于 HashSet、又基于 LinkedHashMap 来实现的。 LinkedHashSet 底层使用 LinkedHashMap(有序) 来保存所有元素,它继承与 HashSet,其所有的方法 操作上又与HashSet相同,因此LinkedHashSet 的实现上非常简单,只提供了四个构造方法,并 通过传递一个标识参数,调用父类的构造器,底层构造一个 LinkedHashMap 来实现,在相关操 作上与父类HashSet的操作相同,直接调用父类HashSet的方法即可

三、Map

在这里插入图片描述

3.1 HashMap

1.底层是数组+链表/红黑树

2.无序键值对集合,根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快 的访问速度。

3.HashMap多只允许一条记录的键为null,允许多条记 录的值为 null。

4.HashMap 非线程安全,如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使 HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。

3.2 Hashtable

Hashtable 是遗留类,很多映射的常用功能与 HashMap 类似,不同的是它承自 Dictionary 类实现Map接口 并且是线程安全的,所有的读写等操作都进行了锁(synchronized)保护,任一时间只有一个线程能写 Hashtable,并发性不如 ConcurrentHashMap, 因为 ConcurrentHashMap 引入了分段锁。Hashtable 不建议在新代码中使用,不需要线程安全 的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换

3.3 TreeMap

TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序, 也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
如果使用排序的映射,建议使用TreeMap。
在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

3.4 LinkedHashMap

LinkedHashMap 是 HashMap 的一个子类,底层结构和HashMap一样,但通过双向链表保存了记录的插入顺序,在用 Iterator 遍历 LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。

注:TreeMap是按照hashcode进行排序的,LinkedHashMap是根据插入顺序进行排序

四、面试题

4.1 list实现类之间的区别

对于需要快速插入、删除元素的场景,应该使用LinkedList

对于需要快速随机访问元素,应该使用ArrayList

对於单线程环境,应该使用非同步的类如ArrayList

对于多线程环境,应该使用同步的类如Vector

4.2 ArrayList和LinkedList的区别?

①ArrayList和LinkedList,一个基于数组实现,一个基于链表实现
前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列
②当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
③当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
④内存空间占用来看,ArrayList的空间浪费体现在会预留一定的容量空间,而LinkedList中存储的每个元素都需要存放前驱和后继的指针,空间占用会比ArrayList中每个元素的多
⑤ArrayList和LinkedList都是线程不安全

场景:
链表,插入删除快,查找修改慢。 适用于频繁增删的场景。
数组,查找快,插入删除慢。 适用于频繁查找和修改的场景。

4.3 ArrayList和Vector的区别?

1.ArrayList是线程不安全的,Vector是线程安全的

2.在不需要保证线程安全时应使用ArrayList,因为Vector在同步操作上会消耗大量时间

4.4 HashMap与HashTable区别

1.HashMap没有对读写等操作进行锁保护,所以是线程不安全的,在多线程场景下会出现数据不一致的问题。而HashTable是同步的,所有的读写等操作都进行了锁(synchronized)保护,在多线程环境下没有安全问题。但是锁保护也是有代价的,会对读写的效率产生较大影响

2.HashMap允许键和值是null,而Hashtable不允许键或者值是null

3.HashMap的迭代器(Iterator)是fail-fast迭代器,但是Hashtable的迭代器(enumerator)不是fail-fast的。如果有其它线程对HashMap进行的添加/删除元素,将会抛出ConcurrentModificationException,但迭代器本身的remove方法移除元素则不会抛出异常。

4.5 Collection 和 Collections的区别?

Collection是集合类的上级接口,继承于他的接口主要有Set 和List.
Collections是针对集合类的一个辅助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作

4.6 Collection集合接口和Map接口有什么关系?

没有直接关系,但是一些子类会有依赖,Collection是最基本的集合接口,声明了适用于JAVA集合(只包括Set和List)的通用方法。Map接口并不是Collection接口的子接口,但是它仍然被看作是Collection框架的一部分。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章