16、集合
一、集合概述
1、为什么使用集合
(1)数组的不足
- 长度开始时必须指定,而且一旦指定不能更改
- 保存必须为同一类型的元素
- 使用数组进行增加、删除元素较麻烦
(2)集合的优点
- 可以动态保存任意多个对象,使用比较方便
- 提供了一系列方便的操作对象的方法
- 使用集合添加删除元素简洁
2、集合的框架
二、Collection接口
public interface Collection<E> extends Iterable<E>
1、Collecting接口
(1)Collection实现子类可以存放多个元素,每个元素可以是Object
(2)有些Collection的实现类可以存放重复的元素,有些不可以
(3)有些Collection的实现类是有序的【List】,有些是无序的【Set】
(4)Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
2、Collection接口遍历元素
(1)方式一:迭代器【Iterator】
【迭代器】
Iterator对象称为迭代器,主要用于遍历Collection集合中的元素
- 所有实现了Collection接口的集合类都有一个
iterator()
方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器 - Iterator仅用于遍历集合,Iterator本身不存放对象
【迭代器的执行原理】
- 得到一个集合的迭代器:
Iterator iterator = coll.iterator();
- 判断是否还有下一个元素:
iterator.hasNext()
- 遍历:
while (iterator.hasNext()) {
sout(iterator.next());
}
(2)方式二:增强for循环
【基本语法】
for (元素类型 元素名 : 集合名或数组名) {
访问元素;
}
三、List接口
1、List接口
List接口时Collection接口的子接口
(1)List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
(2)List集合中每个元素都有其对应的顺序索引【支持索引】
(3)List容器中的每个元素都对应一个整数型的序号记载其在容器的位置,可以根据序号存取容器中的元素
2、List的三种遍历方式
(1)方式一:使用迭代器
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
Object obj = iterator.next();
sout(obj);
}
(2)方式二:增强for
for (Object obj : list) {
sout(obj);
}
(3)方式三:普通for
for (int i = 0; i < list.size(); i++) {
sout(list.get(i));
}
四、ArrayList类
1、ArrayList概述
(1)ArrayList中维护了一个Object类型的数组elementData
来实现数据的存储
(2)当创建ArrayList对象时,如果使用的是指定大小的有参构造器,则elementData容量为指定大小,扩容为原来1.5倍;如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容为10,若再次扩容,则扩容为1.5倍
2、源码分析
【见源码部分】
五、Vector类
1、Vector概述
(1)Vector底层也是一个对象数组
(2)Vector是线程同步的,即线程安全
2、Vector与ArrayList的比较
底层结构 | 效率 | 线程安全 | 扩容倍数 | |
---|---|---|---|---|
ArrayList | 可变数组 | 效率高 | 不安全 | 【有参】 1.5倍 【无参】 (1)初始化容量为10 (2)再次扩容为1.5倍 |
Vector | 可变数组 | 效率较低 | 安全 | 【有参】 2倍 【无参】 (1)初始化容量为10 (2)再次扩容为2倍 |
六、LinkedList类
1、LinkedList概述
(1)LinkedList底层维护了一个双向链表用来存储数据
(2)维护了first
、last
两个属性分别指向首节点和尾节点,实现了双向链表和双端队列的特点
(3)每个节点为【Node对象】,里面维护了prev
【指向前节点】,next
【指向后节点】,item
三个属性实现了双向链表
(2)可以添加任意元素(元素可以重复),包括null
(3)线程不安全,没有实现线程同步
2、源码分析
【见源码部分】
3、ArrayList和LinkedList比较
底层结构 | 增删的效率 | 改查的效率 | |
---|---|---|---|
ArrayList | 可变数组 | 【较低】 数组容量需要变动 |
【较高】 |
LinkedList | 双向链表 | 【较高】 链表追加 |
【较低】 需要遍历 |
(1)如果改查操作较多,选择ArrayList
(2)如果增删较多,选择LinkedList
(3)一般来说,80-90%都是查询,大部分情况选择ArrayList
(4)具体项目中,需要根据业务灵活选择
七、Set接口
1、Set接口
Set接口时Collection的子接口
(1)无序(添加和取出的顺序不一致),无索引
(2)不允许重复元素,最多包含一个null
2、Set接口的遍历方式
因为无索引,则无法用平台for循环
(1)迭代器
(2)增强for
八、HashSet类
(1)HashSet实现Set接口,底层基于HashMap实现,但与HashMap不同在于HashMap存储键值对,HashSet仅存储对象——key
(2)HashSet使用成员对象来计算hashcode值
(3)HashSet的特点
- 无序性
- 唯一性(允许使用null)
- 本质上讲就是HashMap
- HashSet没有提供get方法,和HashMap一样,因为Set内部是无序的,只能通过迭代的方式获得
九、Map接口
1、Map概述
(1)Map与Collection并列存在,用于保存具有映射关系的数据:Key-Value
(2)Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
(3)Map中的key不允许重复,重复会替换
(4)value可以重复
(5)key和value之间存在单向一对一的关系,即通过指定key总能找到对应的value
2、Map六大遍历方式
(1)containsKey:查找键是否存在
(2)keySet:获取所有的键
(3)entrySet:获取所有的键值对
(4)values:获取所有的值
package com.zyhstu.map_.sort_;
import java.util.*;
public class Test {
public static void main(String[] args) {
Map map = new HashMap();
map.put("邓超", "孙俪");
map.put("王宝强", "马蓉");
map.put("宋喆", "马蓉");
map.put("六零波", null);
map.put( null, "刘亦菲");
map.put("鹿晗", "关晓彤");
//1、取出所有key,通过key取出对应的value
Set keyset = map.keySet();
/**Set接口两种遍历方法
* (1)增强for
* (2)迭代器
*/
//(1)增强for
for (Object key : keyset) {
System.out.println(key + "-" + map.get(key));
}
//(2)迭代器
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
/**2、values:获取所有的值
* (1)for循环
* (2)增强for循环
* (3)迭代器
*/
Collection values = map.values();
for (Object value : values) {
System.out.println(value);
}
Iterator iterator = values.iterator();
while (iterator.hasNext()) {
Object value = iterator.next();
System.out.println(value);
}
//3、通过entrySet:获取所有键值对
Set entrySet = map.entrySet();
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
for (Object o : entrySet) {
Map.Entry m = (Map.Entry) o;
System.out.println(m.getKey() + "-" + m.getValue());
System.out.println(o);
}
}
}
十、HashMap类
(1)key不能重复,但是value可以重复,运行使用null键和null值
(2)如果添加相同的key会覆盖原来的键值对,等同于修改
(3)底层以hash表的方式存储数据,则不保证映射顺序
(4)线程不安全
十一、如何选择集合实现类
十二、Collections工具类
1、Collections工具类概述
(1)Collections是一个操作Set、List和Map等集合的工具类
(2)Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作
2、排序操作(静态方法)
(1)reverse(List
)`:反转list中元素的顺序
(2)shuffle(List)
:对List集合元素进行随机排序
(3)sort(List)
:根据元素的自然排序对指定List集合元素按升序排序
(4)sort(List, Cpmparator)
:根据指定的Comparator产生的顺序对List集合元素进行排序
(5)swap(List, int, int)
:将指定List集合中的i处元素和j处元素进行交换
3、查找、替换
(1)Object max(Collection)
:根据元素的自然顺序,返回给定集合中的最大元素
(2)Object max(Collection, Comparator)
:根据Comparator指定的顺序,返回给定集合中的最大元素
(3)Object min(Collection)
(4)Object min(Collection, Object)
(5)int frequency(Collection, Object)
:返回指定集合中指定元素的出现次数
(6)void copy(List dest, List src)
:将sec的内容复制到dest中
(7)boolean replaceAll(List list, Object oldVal, Object newVal)
:使用新值替换List对象的所有旧值