集合进阶
- 1 集合体系结构
- 2 ArrayList底层原理
1 集合体系结构
总体上分为两类:
-
Collection 单列集合 祖宗接口
- List:添加元素有序(存取顺序一致)、可重复、有索引
- ArrayList
- LinkedList
- Vector
- Set:添加的元素是无序(存取顺序可能不同)、不重复、无索引
- HashSet
- LinkedHashSet
- TreeSet
- HashSet
Collection接口常用方法
public boolean add(E e) //把给定对象添加到当前集合中 public void clear() //清空集合中所有元素 public boolean remove(E e) //把指定对象删除 public boolean contains(Object obj) //判断当前集合是否包含指定对象,底层用equals()方法实现 public boolean isEmpty() //判断当前集合是否为空(根据长度) public int size() //返回集合长度
Conllection遍历方式
-
迭代器遍历(不依赖索引)(程序运行时迭代器不会复位)
//Collection集合获取迭代 Iterator<E> iterator() //返回迭代器对象,默认指向当前集合0索引 //Iterator中的常用方法 boolean hasNext() //判断当前位置是否有元素 E next() //获取当前位置元素,并将迭代器对象后移 void remove //删除当前元素 //迭代器无法添加
-
增强for遍历(JDK5,底层就是迭代器,目的是简化迭代器书写。)(单列集合和数组)
//格式 for(元素的数据类型 变量名:数组或者集合){ } //示例 for(String s:list){ System.out.println(s); }
-
lambda表达式调用
default void forEach(Consumer<? super T> action):
- List:添加元素有序(存取顺序一致)、可重复、有索引
-
Map 双列集合
2 ArrayList集合底层原理
-
利用空参创建的集合,在底层创建一个默认 *** 长度为0的数组 *** 。
-
添加第一个元素时,底层会创建一个新的 *** 长度为10的数组 *** 。
-
存满时,扩容1.5倍。
-
如果一次添加多个元素,1.5倍放不下,则新数组长度以实际为准。
3 LinkedList
- 底层数据结构是双链表,查询慢,增删快,但如果是首尾元素,速度也是极快的
- 提供了很多直接操作首位元素的api
特有方法:public void addFirst(E e) //在该列表开头插入指定元素 public void add Last(E e) //尾插 public E getFirst() //返回第一个元素 public E getLast() //返回最后一个元素 public E removeFirst() //头删 public E removeLast() //尾删
4 迭代器Iterator底层
- 底层创建一个内部类对象Itr,这个内部类是对应集合的迭代器
5 HashSet (无序、不重复、无索引)
- HashSet集合底层采取哈希表储存
- 哈希表是一种对于增删改查数据性能都较好的结构
- 哈希表:JDK-8之前由数组+链表组成;JDK-8之后数组+链表+红黑树
5.1 哈希值
- 根据hashCode方法算出来的int类型整数
- 该方法定义在Object类中,所有对象都可调用,默认用地址值进行计算
- 一般会重写hashCode方法,利用对象内部属性值计算哈希值
计算:int index=(数组长度-1) & 哈希值;
5.2 底层原理
-
创建一个默认长度为16,默认加载因子为0.75的数组,数组名table。
-
根据元素的哈希值和数组长度,计算出应存入位置
-
判断当前位置是否为null,如果null直接存入
-
如果不为null,表示有元素,则用equals方法比较属性值
-
如果一样,则不存,若不一样,存入数组,形成链表。
JDK-8以前:老元素挂在新元素下面
JDK-8以后:新元素挂在老元素下面 -
当数组里存入元素数量=长度*加载因子(0.75)时,数组将扩容为原先2倍
-
当链表长度>8且数组长度>=64, 当前链表自动转成红黑树
6 LinkedHashSet (有序、不重复、无索引)
- LinkedHashSet保证存储和取出的数据一致
原理:底层数据结构依然是哈希表,只是每个元素又额外多了一个双链表机制记录存储的顺序
7 TreeSet (可排序、不重复、无索引)
-
按照元素默认规则(由大到小)排序
- 对于数值类型,默认由大到小排序
- 对于字符、字符串类型:按照字符在ASCII码表中的数字升序进行排序
- 对于对象
- 方式1:自然排序(实现Comparable接口):return this.xxx-o.xxx(升序)
- 方式2:比较器排序(创建TreeSet对象时,传递比较器Comparator指定规则,o1-o2)
-
底层基于红黑树实现,增删改查性能好