集合,个人理解

学了一天关于集合方面的知识,纯属个人理解,总结一下

 

Collection接口:List、Set

List---ArrayList、LinkedList、Vector、Stack

Set---HashSet、TreeSet

 

Map接口:HashMap、TreeMap 

Map不是集合

 

 

关于List和Set

List可通过下标进行对元素的访问,但插入元素时把后面的数据往后挪一位,比较困难

Set不能随机访问元素,但由于是链表结构,插入数据较为方便

 

Array和ArrayList

Array只能放入对象,ArrayList可以放入对象和基本数据类型。但Array对存储对象的方法进行封装能更加高效,所以我们在选择 集合类型时 先考虑 数据类型是什么。

Array是固定大小的,ArrayList有动态大小的,有自动扩容的方法

当指定大小时,建议使用Array

 

ArrayList和LinkedList和Vector

LinkedList 在插入和删除数据时效率更高,ArrayList 在查找某个 index 的数据时效率更高

LinkedList 比 ArrayList 需要更多的内存

Vector和ArrayList差不多相同,但Vector是线程安全的

Vector 在数据满时(加载因子1)增长为原来的两倍(扩容增量:原容量的 2 倍),而 ArrayList 在数据量达到容量的一半时(加载因子 0.5)增长为原容量的 (0.5 倍 + 1) 个空间。

 

TreeSet的不可重复性

public boolean add(E e) {
    return map.put(e, PRESENT)==null;// 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值
}
TreeSet的add()方法,底层实际上就是一个HashMap,但他的每个Value值都是一样的虚值(没有意义),因此如果Key相同的话,则会覆盖原来的。

  

 

当一个集合被作为参数传递给一个函数时,如何才可以确保函数不能修改它?

 在作为参数传递之前,使用Collections.unmodifiableCollection(Collection c)方法创建一个只读集合,这将确保改变集合的任何操作都会抛出UnsupportedOperationException。

 

集合的转换

Collections静态类,用于操作 一个集合。如 集合的排序  Collection.sort()

Arrays静态类,用于操作一个数组。如 将数组 排序成集合 Arrays.sort()

 

fail-fast和fail-safe

迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量,如果数据结构发生了变化,将modCount变为expectedmodCount,

在下次遍历next()时,如果modCount !=  expectedmodCount,则会抛出异常,中止遍历。否则继续遍历

在遍历过程中,所有涉及到改变modCount值得地方全部加上synchronized, 或使用CopyOnWriteArrayList来替换ArrayList,则可以避免fail-fast机制

一般使用concurrent的集合都是fail-safe的,可在多线程下并发使用,并发修改

原理是,使用 集合时,并不是使用原来的集合,而是复制一个新的集合,用新的进行遍历,因此不会检测到对 原来集合数据的修改

 

HashMap的一些理解

使用HashMap初始化大小时,根据参数的二进制和负载因子进行扩容。

例如:

  如果初始大小是10000时,传入10000条数据,HashMap是否会扩容?

答:并不会,如果初始化大小是10000,那根据底层的实现tableSizeFor,容量会变成2 ^14 * 0.75的大小,还有剩;

  但如果是1000,则会是2^10*0.75,还不够1000;

因此我们初始大小时,应该选择 大小*0.75的容量来进行初始化

 

 

 

posted @ 2019-11-15 14:18  小萌豚  阅读(123)  评论(0编辑  收藏  举报