java—java集合
文章目录
- list、set、map的区别
- 如何选用集合
- List
- ArrayList 和 LinkdList 的异同点
- ArrayList 和 Vector 的区别
- Arrays 和 ArrayList的区别
- ArrayList的自动扩容机制
- Set
- Map
- map的分类
- map的三种遍历方式
————————————————————————————————
list、set、map的区别
- List(对付顺序的好帮手): 存储的元素是有序的、可重复的。
- Set(注重独一无二的性质): 存储的元素是无序的、不可重复的。
- Map`(用 Key 来搜索的专家): 使用键值对(kye-value)存储,Key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
如何选用集合
主要根据集合的特点来选用,比如我们需要根据键值获取到元素值时就选用 Map
接口下的集合,需要排序时选择 TreeMap
,不需要排序时就选择 HashMap
,需要保证线程安全就选用 ConcurrentHashMap
。
当我们只需要存放元素值时,就选择实现Collection
接口的集合,需要保证元素唯一时选择实现 Set
接口的集合比如 TreeSet
或 HashSet
,不需要就选择实现 List
接口的比如 ArrayList
或 LinkedList
,然后再根据实现这些接口的集合的特点来选用。
List
- ArrayList:底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
- LinkedList 底层数据结构是双向链表,查询慢,增删快,线程不安全,效率高,可以存储重复元素(JDK1.6 之前为循环链表,JDK1.7 取消了循环。)
- Vector:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素
ArrayList 和 LinkdList 的异同点
①:首先 ArrayList 和 LinkedList 都是线程不安全的
②:然后 ArrayList 底层使用的是 Object 数组,所以插入和删除元素的时间复杂度受元素位置的影响,比如 add一个元素,ArrayList会默认将元素加到列表的末尾,这种情况时间复杂度就是O(1);如果要在指定位置 i 插入和删除元素 的话时间复杂度就为O(n)。因为在进行上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。
但是LinkedList 底层使用的是双向链表结构,所以插入、删除元素时间复杂度不受元素位置的影响,都是O(1);
④:还有就是ArrayList支持通过索引访问元素对象。
⑤:ArrayList 的空 间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。
ArrayList 和 Vector 的区别
Vector在关键性的方法前面都加了 synchronized关键字,来保证线程的安全性。如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
ArrayList在底层数组不够用时在原来的基础上扩展0.5倍,Vector是扩展1倍,ArrayList更节约内存空间。
Arrays 和 ArrayList的区别
- Array可以包含基本类型和引用类型,ArrayList只能包含引用类型。
- Array大小是固定的,ArrayList的大小是动态变化的。
- ArrayList 提供了更多的方法和特性,比如:addAII(), removeAII(), iterator()等等。
ArrayList的自动扩容机制
ArrayList 是一个数组结构的存储容器,默认情况下,数组的长度是 10。 当然我们也可以在构建 ArrayList 对象的时候自己指定初始长度。随着在程序里面不断的往ArrayList中添加数据,当添加的数据达到10个的时候,ArrayList 就没有多余容量可以存储后续的数据。这个时候 ArrayList 会自动触发扩容。
扩容的具体流程很简单:
首先,创建一个新的数组,这个新数组的长度是原来数组长度的 1.5 倍。然后使用 Arrays.copyOf 方法把老数组里面的数据拷贝到新的数组里面。扩容完成后再把当前要添加的元素加入到新的数组里面,从而完成动态扩容的过程。
Set
- HashSet底层数据结构采用哈希表实现,元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
HashSet
会先计算对象的hashcode
值来判断对象加入的位置,同时也会与其他加入的对象的 hashcode
值作比较,如果没有相符的 hashcode
,HashSet
会假设对象没有重复出现。但是如果发现有相同 hashcode
值的对象,这时会调用equals()
方法来检查 hashcode
相等的对象是否真的相同。如果两者相同,HashSet
就不会让加入操作成功。
- LinkedHashSet底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
- TreeSet底层数据结构采用红黑树来实现,元素唯一且已经排好序;
注意:存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。Set接口不保证维护元素的次序。
Map
map的分类
-
HashTable是同步的,线程安全,所有方法都加了synchronized关键字,底层数组+链表 key和value的值均不允许为null
-
HashMap 根据哈希值存储,无序的,允许多条记录的Value为 Null
-
TreeMap非线程安全基于红黑树实现。根据key排序,默认是按升序排序 不允许key的值为null
-
LinkedHashMap 保存了记录的插入顺序
map的三种遍历方式
- keySet:获取所有的键
- entrySet:获取所有关系k-v
- values:获取所有的值