ArrayList
底层结构
数组 Object[] elementData;
特点
根据索引查询遍历效率较高,增删效率低
应用场景
适用于大量做查询少量做增删的位置
扩容问题
初始容量
默认初始容量为10 ,在第一次添加add的时候进行构建
扩容机制
每次扩容原容量的1.5倍
新增功能
forEach(Consumer<? super E> action)
遍历每个元素
写法:list.forEach(System.out::println)
遍历方法
普通for
增强for
iterator迭代器
listIterator迭代器
Vector
与ArrayList区别
1) Vector是同步的|线程安全
ArrayList不同步|线程不安全,相对效率较高
2) Vector每次扩容原容量的2倍
ArrayList每次扩容原容量的1.5倍,相对ArrayList更有利于节省内存
LinkedList
底层结构:双向链表
单向链表:记录链表头节点
双向链表:记录上下链表节点
特点
查询效率低,增删效率高
应用场景
单个数据值的集合中,允许数据有序,且可重复,在大量做增删,销量做查询的时候时候适合使用链表
存储javabean类型数据时候,要求javabean类型重写equals方法,否则使用一些判断比较的方法时候回默认调用equals方法
Collection集合层次结构中的根接口
Set无序不可重复
存储元素是没有顺序的,可以存储null
去重,去除重复的元素
新增功能: static <E> Set<E> of(E... elements) 返回包含任意数量元素的不可修改集。
常用实现类
HashSet
AbstractSet
常用方法
add()添加元素
contains()查找是否存在某个元素
遍历方式
foreach
iterator迭代器
List有序可重复,有索引
listiterator列表迭代器
新增方法:一些列根据索引操作的方法
常用方法
add()添加元素
contains()查找是否存在某个元素
get()指定位置添加元素
lastIndexOf(Object o)返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-1。
set(int index, E element)用指定的元素替换此列表中指定位置的元素
subList(int fromIndex, int toIndex)返回指定索引区间的元素,不包括后面索引的那个元素
常用实现类
ArrayList
LinkedList
遍历方式
for普通for循环
foreach
iterator迭代器
Treeset
底层结构
红黑树
特点
查询效率较高,自动把数据做升序排序
注意 : TreeSet需要存储相同类型的数据,因为会默认存在比较排序
Comparable接口内部比较器
javabean类型实现Comparable接口,重写compareTo(T o)方法,在方法中定义比较规则
Comparator接口外部比较器
遍历方法
foreach iterator迭代器
HashSet
底层结构
哈希表(数组+链表+红黑树)
特点
查询,增删效率高 ,去重,无序
遍历方法
foreach iterator迭代器
遍历方式
foreach
iterator迭代器
Map接口
HashMap
特点
1.存储的元素是以K-V的形式存在的
2.map集合中 key 必须要唯一,如果添加了相同的键值对(键相同)会发生覆盖
3.map集合中元素(键值对)是无序的,和Set集合类似
K键 : 无序的,去重的|唯一的 ---> Set
V值 : 无序的,可重复 ---> Collection
K-V可以为任意引用数据类型
基于哈希表的Map接口的实现。 此实现提供了所有可选的映射操作,并允许null值和null键。
底层结构
哈希表(数组+链表+红黑树)
初始容量:哈希表中的数组默认的初始长度 16
加载因子: 0.75 一般不建议改变
扩容阀值 threshold : 扩容的临界值 数据的个数size>数组的长度*加载因子 就会扩容
扩容机制: 原容量的2倍 int newCap = oldCap << 1
通过哈希表存储数据的过程
1.根据key计算哈希值
通过key的hashCode方法的返回值进一步进行hash算法的运算,得到的整数
int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
2.调用putVal方法实现添加数据(hash,key,value)
1)判断是否是第一次调用put方法做添加 if ((tab = table) == null || (n = tab.length) == 0)
如果是第一次添加,直接调用resize()实现扩容
2)计算位桶的索引 int index = (n - 1) & hash
3)判断哈希表结构的数组table[index]是否存在数据,
如果不存在数据,证明没有头节点,创建新节点,放入当前数组的对应索引位置作为头节点
table[index] = new Node<>(hash, key, value, next);
size数据的个数+1,判断是否>扩容的阀值,如果大于需要调用resize方法进行扩容,如果不大于,不需要扩容直接返回null
if (++size > threshold) resize();
return null;
如果存在数据,作为链表的头结点,遍历这个链表,拿到每一个节点的key与hash值判断是否与要添加的key和hash相同,如果相同,value覆盖
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
value覆盖之后,返回被覆盖的value
V oldValue = e.value;
e.value = value;
return oldValue;
遍历方式
1.values 获取所有键值对的值
Collection<V> values() 返回此映射中包含的值的Collection视图。
2.keySet将所有的 key 获取存入 Set 集合中,遍历存储 key 的 Set 集合,结合 get(key) 方法可以获取map 中
每一个 key 以及对应的 value。
Set<K> keySet() 返回此映射中包含的键的Set视图。
3.entrySet 将Map集合中的每一个键值对作为一个 Entry 对象获取到一个Set集合中,通过对象的 getKey 和 getValue 方法获取 key 和 value
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射的Set视图。
TreeMap
底层结构
红黑树
存储键值对类型的数据,自动升序排序,去重的
去重,排序: 根据键值对的key实现,与value本身无关
Hashtable 与 HashMap之间的区别
共同点
都是Map接口的实现类,底层结构都是哈希表
区别
1.继承体系不同
2.线程是否安全不同
HashMap 线程不安全|不同步
Hashtable 线程安全的|同步的
3.扩容机制不同
HashMap扩容机制 : 每次扩容原容量的2倍
int newCap = oldCap << 1
Hashtable扩容机制 : 原容量的2倍+1
4.键值对数据null值的要求不同
HashMap 可以存储null值的key与value
Hashtable key与value都不为null
5.计算hash值与位桶索引index的算法不同
HashMap :
int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
int index = (n - 1) & hash
Hashtable :
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
工具类
Properties是Hashtable的子类,要求键与值只能为字符串 ,不能为null
Collections
void sort(List) //对List容器内的元素排序,排序的规则是按照升序进行排序。
void shuffle(List) //对List容器内的元素进行随机排列
void reverse(List) //对List容器内的元素进行逆续排列
void fill(List, Object) //用一个特定的对象重写整个List容器
int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的方法查找特定对象
泛型
数据类型作为参数传递,只能配置引用数据类型
泛型发生在编译期间,要求先定义泛型,才能使用泛型
优点
代码简单简洁
增强程序健壮性,避免类型转换异常的出现
增强稳定性与可读性