JAVA容器——Set、List、Map

目录

一、Collection:

1、Set

TreeSet:

HashSet:

LinkedHashSet:

2、List

ArrayList:

Vector:

LinkedList:

LinkedList与 ArrayList 的比较

3、Queue

LinkedList:

PriorityQueue:

二、Map

TreeMap:

HashMap( 数组+链表+红黑树):

HashTable:

LinkedHashMap:

HashTable与HashMap区别:



容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存 储着键值对(两个对象)的映射表。

一、Collection:

1、Set

Set 注重独一无二的性质,值不能重复,对象的相等性本质是对象 hashCode 值。

TreeSet

基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1), TreeSet 则为 O(logN)。 Integer 和 String 对象都可以进行默认的 TreeSet 排序,而自定义类的对象是不可以的,自己定义的类必须实现 Comparable 接口,并且覆写相应的 compareTo()函数。

HashSet

基于哈希表实现,支持快速查找,但不支持有序性操作。并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的。 元素的哈希值是通过元素的hashcode 方法来获取的, HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals 方法 如果 equls 结果为 true ,HashSet 就视为同一个元素。如果 equals 为 false 就不是同一个元素。HashSet 通过 hashCode 值来确定元素在内存中的位置。一个 hashCode 位置上可以存放多个元素。(链地址法)

LinkedHashSet

具有 HashSet 的查找效率,且内部使用双向链表维护元素的插入顺序

2、List

ArrayList

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

实现了 RandomAccess 接口,因此支持随机访问。数组的默认大小为10.

动态扩容特性

Vector

和 ArrayList 类似,通过数组实现,但它是线程安全的。 支持线程的同步,即某一时刻只有一个线程能够写 Vector,但是实现同步的代价较高,访问会较慢。

LinkedList

基于双向链表实现,只能顺序访问,但是可以快速地在链表中间 插入和删除元素,随机访问和遍历速度比较慢。不仅如此,LinkedList 还可以用作栈、队列和双向队列。

LinkedList ArrayList 的比较

ArrayList 基于动态数组实现,LinkedList 基于双向链表实现;

ArrayList 支持随机访问,LinkedList 不支持;

LinkedList 在任意位置添加删除元素更快。

3、Queue

LinkedList

可以用它来实现双向队列。

PriorityQueue

基于堆结构实现,可以用它来实现优先队列


二、Map

TreeMap

基于红黑树实现,可排序。实现 了SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。

在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。

HashMap( 数组+链表+红黑树)

基于哈希表实现。HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap 最多只允许一条记录的键为 null,允许多条记录的值为 null。HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。

根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为 O(n)。为了降低这部分的开销,在 Java8 中,当链表中的元素超过了 8 个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。

拉链法:解决哈希冲突,即在相同哈希值的对应位置加上单链表,使用头插法。

HashTable

和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。它是遗留类,不应该去使用它。现在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高,因为 ConcurrentHashMap 引入了分段锁。

LinkedHashMap

使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序。

HashTableHashMap区别:

HashTable 使用 synchronized 来进行同步。

HashMap 可以插入键为 null 的 Entry。

 HashMap 的迭代器是 fail-fast 迭代器。

HashMap 不能保证随着时间的推移 Map 中的元素次序是不变的。


只是整理了JAVA集合的一些基本概念,更深入的源码分析,以后有能力有机会再完成吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值