Java 集合
- Java 集合
- 前言
- 目标
- 1. 什么是集合
- 1.1 Collection
- 1.2 Map
- 2. 集合的应用场景
- 2.1 数组与集合
- 2.2 集合应用场景
- 3. List 集合
- 3.1 概念和特性
- 3.2 ArrayList 实现类
- 3.2.1 构造方法
- 3.2.2 常用成员方法
- 3.3 实例
- 3.3.1 新增元素
- 3.3.2 泛型初识
- 3.3.3 删除元素
- 3.3.4 修改元素
- 3.3.5 查询元素
- 3.2.7 自定义类的常用操作
- 3.4 LinkedList 实现类
- 3.4.1 构造方法
- 3.4.2 常用成员方法
- 4. Set 集合
- 4.1 概念和特性
- 4.2 HashSet 实现类
- 4.2.1 构造方法
- 4.2.2 常用成员方法
- 4.3 实例
- 4.3.1 新增元素
- 4.3.2 删除元素
- 4.3.3 查询元素
- 4.3.4 自定义类的常用操作
- 5. Map 集合
- 5.1 概念和特性
- 5.2 HashMap 实现类
- 5.2.1 构造方法
- 5.2.2 常用成员方法
- 5.3 实例
- 6. 小结
Java 集合
前言
- 8.27
- 不要停止我的音乐和编程学习
- Java是第一次认认真真系统学的语言,一定要系统的全面的学好!
- 奥里给!!!
- 没有什么能够阻挡
目标
- 什么是集合
- 集合的应用场景
- 对比 Java 数组与集合的区别
- Java 集合的架构
- 结合实例来讲解集合的实际应用
1. 什么是集合
在计算机科学中,集合是一组可变数量的数据项(也可能为 0 个)的组合,这些数据可能共享某些特征,需要以某种操作方式一起进行操作。
Java 中集合主要分为java.util.Collection和java.util.Map两大接口。
Java 集合的框架:

Tips: 图表最下方的
ArrayList、LinkedList、HashSet以及HashMap都是常用实现类
1.1 Collection
java.util.Collection接口的实现可用于存储 Java 对象。例如,NBA的所有球员(集合)可以视为一个Collection(存储类对象)。
Collection又可以分为三个子接口,分别是:
-
List:序列,必须按照顺序保存元素,因此它是有序的,允许重复; -
Queue:队列,按照排队规则来确定对象产生的顺序,有序,允许重复; -
Set:集,不能重复。
1.2 Map
java.util.Map接口的实现可用于表示“键”(key)和“值”(value)对象之间的映射。一个映射表示一组“键”对象,其中每一个“键”对象都映射到一个“值”对象。因此可以通过键来查找值。
如:
NBA的每一个球员都有他自己的球员号码,这个关联关系可以用Map来表示。
2. 集合的应用场景
2.1 数组与集合
在介绍集合的应用场景之前,我们先来看看数组和集合的对比。
我们知道数组和集合都用于存放一组数据,但数组的容量是固定大小的,而集合的容量是动态可变的;
对于可存放的数据类型,数组既可以存放基本数据类型又可以存放引用数据类型,而集合只能存放引用数据类型,基本数据类型需要转换为对应的包装类才能存放到集合当中。
2.2 集合应用场景
- 无法预测存储数据的数量:由于数组容量是固定大小,因此使用集合存储动态数量的数据更为合适;
- 同时存储具有一对一关系的数据:例如存储NBA球员的号码,为了方便检索对应NBA球员的号码,可使用
Map将NBA球员的uid和对应的号码进行一对一关联; - 数据去重:使用数组实现需要遍历,效率低,而
Set集合本身就具有不能重复的特性; - 需要数据的增删:使用数组实现增删操作需要遍历、移动数组中元素,如果操作频繁会导致效率降低。
3. List 集合
3.1 概念和特性
List 是元素有序并且可以重复的集合,称之为序列。序列可以精确地控制每个元素的插入位置或删除某个位置的元素。通过前面的学习,我们知道List是Collection的一个子接口,它有两个主要实现类,分别为ArrayList(动态数组)和LinkedList(链表)。
3.2 ArrayList 实现类
ArrayList 可以理解为动态数组,它的容量可以动态增长。当添加元素时,如果发现容量已满,会自动扩容为原始大小的 1.5 倍。
3.2.1 构造方法
-
ArrayList():构造一个初始容量为 10 的空列表; -
ArrayList(int initialCapacity):构造一个指定容量的空列表; -
ArrayList(Collection<? extends E> c):构造一个包含指定集合元素的列表,其顺序由集合的迭代器返回。
在代码中,我们可以这样实例化ArrayList对象:
3.2.2 常用成员方法
-
void add(E e):将指定的元素追加到此列表的末尾; -
void add(int index, E element):将指定的元素插入此列表中的指定位置; -
E remove(int index):删除此列表中指定位置的元素; -
boolean remove(Object o):如果存在指定元素,则从该列表中删除第一次出现的该元素; -
void clear():从此列表中删除所有元素; -
E set(int index, E element):用指定的元素替换此列表中指定位置的元素; -
E get(int index):返回此列表中指定位置的元素; -
boolean contains(Object o):如果此列表包含指定的元素,则返回 true,否则返回 false; -
int size():返回该列表中元素的数量; -
Object[] toArray():以正确的顺序(从第一个元素到最后一个元素)返回一个包含此列表中所有元素的数组。
3.3 实例
3.3.1 新增元素
运行结果:
代码中,首先实例化了一个ArrayList对象,然后使用 for 循环语句循环 5 次,每次都向arrayList对象中追加变量i,并打印列表内容,运行结果清晰的展示了每次新增元素的过程。
Tips:由于
ArrayList的父类AbstractCollection重写了toString()方法,因此直接打印列表,可以直观地展示出列表中的元素。
3.3.2 泛型初识
Tips:泛型(
Genericity)介绍一下泛型以及其使用方法。
如果你使用IDEA编写如上代码,将会有下图所示的 3 处黄色警告:

既然IDE有了警告,我们就尝试来解决一下,将鼠标光标放置到警告处,会提示“Unchecked call to ‘add(E)’ as a member of raw type ‘java.util.List’ ”,这是IDE的泛型检查,可点击Try to generify 'ArrayListDemo1.java'按钮:

此时会出现一个Generify的弹窗,直接点击Refactor按钮:

代码变成了下图所示的样子,那 3 处警告被成功消除了:

List类型后面多了一对尖括号“<>”,<>里面是 Java 的包装类型Integer,在ArrayList类型后面也多了一对尖括号,这里的<>中承载的就是 Java 的泛型的类型参数,它表示arrayList对象用于存放Integer类型的数据。
我们只需知道这样做就可以消除IDEA的警告即可。后面会继续深入!
由于前面List已经指定了泛型的参数类型为Integer,后面的ArrayList就不需要再重复指定了。当然你也可以这样写(但是没必要):
同理,如果你想向arrayList存放String类型的元素,只需将<Integer>改为<String>,我们再来看一个实例:
实例演示

两种形式,直接最后添加字符换或者指定索引添加,IDEA这点做的还是挺好的!!!
代码中,首先实例化了一个ArrayList的对象,调用了两次add(E e)方法,依次向列表尾部插入了Hello和World元素,列表中元素为[Hello, World],此时调用add(int index, E element)方法,将字符串元素 Java 插入到此列表中的索引为 1 的位置,因此列表中的元素为[Hello, Java, World]。
3.3.3 删除元素
实例演示
运行结果:
代码中,我们首先添加了 4 个字符串元素,列表内容为[Hello, World, Hello, Java],然后调用remove(int index)方法删除了索引位置为 3 的元素(即Java),此时列表内容为[Hello, World, Hello] ,再次调用remove(Object o)方法,删除了列表中第一次出现的Hello元素,此时列表内容为[World, Hello]。
奥里给!!!!
3.3.4 修改元素
可使用set()方法修改列表中元素,实例如下:
实例演示
运行结果:
3.3.5 查询元素
可使用get()方法来获取列表中元素,实例如下:
实例演示
运行结果:
我们在使用for循环遍历列表的时候,让限定条件为i < arrayList.size();,size()方法可获取该列表中元素的数量。
3.2.7 自定义类的常用操作
请查看如下实例:
实例演示
运行结果:
为了方便演示,我们定义了一个静态内部类NBA,它有两个属性name和position,定义了属性的getter和setter,并重写了toString()方法。在main()方法中,我们实现了自定义类在ArrayList中的增删改查。
3.4 LinkedList 实现类
LinkedList 是一个以双向链表实现的List。和ArrayList一样,也按照索引位置排序,但它的元素是双向连接的,因此顺序访问的效率非常高,而随机访问的效率比较低。
3.4.1 构造方法
-
LinkedList():构造一个空列表; -
LinkedList(Collection<? extends E> c):构造一个包含指定集合元素的列表,其顺序由集合的迭代器返回。
3.4.2 常用成员方法
-
void add(E e):将指定的元素追加到此列表的末尾; -
void add(int index, E element):将指定的元素插入此列表中的指定位置; -
void addFirst(E e):将指定的元素插入此列表的开头; -
vod addLast(E e):将指定的元素添加到此列表的结尾; -
E remove(int index):删除此列表中指定位置的元素; -
boolean remove(Object o):如果存在指定元素,则从该列表中删除第一次出现的该元素; -
void clear():从此列表中删除所有元素; -
E set(int index, E element):用指定的元素替换此列表中指定位置的元素; -
E get(int index):返回此列表中指定位置的元素; -
E getFirst():返回此列表的第一个元素; -
E getLast():返回此列表的最后一个元素; -
boolean contains(Object o):如果此列表包含指定的元素,则返回 true,否则返回 false; -
int size():返回该列表中元素的数量; -
Object[] toArray():以正确的顺序(从第一个元素到最后一个元素)返回一个包含此列表中所有元素的数组。
4. Set 集合
4.1 概念和特性
Set是元素无序并且不可以重复的集合,我们称之为集(有序可以重复成为序列)。Set是Collection的一个子接口,它的主要实现类有:HashSet、TreeSet、LinkedHashSet、EnumSet等,下面我们将详细介绍最常用的HashSet实现类。
4.2 HashSet 实现类
HashSet类依赖于哈希表(实际上是HashMap实例,下面将会介绍)。HashSet中的元素是无序的、散列的。
4.2.1 构造方法
-
HashSet():构造一个新的空集;默认的初始容量为 16(最常用),负载系数为 0.75; -
HashSet(int initialCapacity):构造一个新的空集; 具有指定的初始容量,负载系数为 0.75; -
HashSet(int initialCapacity, float loadFactor):构造一个新的空集; 支持的 HashMap 实例具有指定的初始容量和指定的负载系数; -
HashSet(Collection<? extends E> c):构造一个新集合,其中包含指定集合中的元素。
4.2.2 常用成员方法
HashSet的常用成员方法如下:
-
boolean add(E e):如果指定的元素尚不存在,则将其添加到该集合中; -
boolean contains(Object o):如果此集合包含指定的元素,则返回 true,否则返回 false; -
boolean isEmpty():如果此集合不包含任何元素,则返回 true,否则返回 false; -
Iterator<E> iterator():返回此集合中元素的迭代器; -
boolean remove(Object o):从该集合中删除指定的元素(如果存在); -
int size():返回此集合中的元素数量。
4.3 实例
4.3.1 新增元素
实例演示
运行结果:
在实例中,我们先后向hashSet中添加了两次Monkey元素,由于集的元素不可重复特性,因此集中只允许出现一个Monkey元素。我们还观察到,打印结果的元素顺序和我们添加的顺序是不同的,这验证了集的无序特性。
Tips: 由于
HashSet的父类AbstractCollection重写了toString()方法,因此直接打印集,可以直观地展示出集中的元素。
4.3.2 删除元素
可使用remove()方法删除集中元素
实例演示
运行结果:
4.3.3 查询元素
我们知道了ArrayList 通过 get方法来查询元素,但HashSet没有提供类似的get方法来查询元素。
这里我们介绍一个迭代器(Iterator)接口,所有的Collection都实现了Iterator接口,它可以以统一的方式对各种集合元素进行遍历。我们来看下Iterator接口的常用方法:
-
hasNaxt() 方法检测集合中是否还有下一个元素; -
next()方法返回集合中的下一个元素; -
iterator():返回此集合中元素的迭代器。
实例如下:
实例演示
运行结果:
4.3.4 自定义类的常用操作
请查看如下实例:
实例演示
运行结果:
为了方便演示,我们定义了一个静态内部类ImoocStudent,它有两个属性nickname和position,定义了属性的getter和setter,并重写了toString()方法。在main()方法中,我们实现了自定义类在HashSet中的增删改查,使用迭代器可以遍历元素。
5. Map 集合
5.1 概念和特性
我们已经知道Map是以键值对(key-value)的形式存储的对象之间的映射,key-value是以java.util.Map.Entry类型的对象实例存在。
可以使用键来查找值,一个映射中不能包含重复的键,但值是可以重复的。每个键最多只能映射到一个值。
5.2 HashMap 实现类
HashMap是java.util.Map接口最常用的一个实现类,前面所学的HashSet底层就是通过HashMap来实现的,HashMap允许使用null键和null值。
5.2.1 构造方法
-
HashMap():构造一个新的空映射;默认的初始容量为 16(最常用),负载系数为 0.75; -
HashMap(int initialCapacity):构造一个新的空映射; 具有指定的初始容量,负载系数为 0.75; -
HashMap(int initialCapacity, float loadFactor):构造一个新的空映射; 支持的 HashMap 实例具有指定的初始容量和指定的负载系数; -
HashSet(Map<? extends K, ? extends V> m):构造一个新映射,其中包含指定映射相同。
5.2.2 常用成员方法
-
void clear():从该映射中删除所有映射; -
Set<Map, Entry<K, V>> entrySet:返回此映射中包含的映射的集合; -
V get(Object key):返回指定键映射到的值,如果该映射不包含键的映射,则返回 null; -
Set<K> keySet:返回此映射中包含的键的结合; -
V put(K key, V value):将指定值与此映射中指定键关联; -
V remove(Object key):如果存在,则从此映射中删除指定键的映射。 -
Collection<V> values:返回此映射中包含的集合。
5.3 实例
下面我们使用 HashMap 来实现一个英汉字典的例子。
实例演示
运行结果:
实例中,Map 的 key 是字符串类型,value 也是字符串类型。值得注意的是,我们在创建HashMap的时候,在Map类型的后面有一个<String, String>,分别表示映射中将要存放的 key 和 value 的类型都为 String 类型。在遍历映射的时候,我们调用了entrySet方法,它返回了此映射中包含的映射的集合。通过键查找值,我们可以调用keySet方法来获取映射中的键的集合,并且遍历这个集合即可找到对应键,通过键就可以获取值了。
6. 小结
Java 的集合,它们定义在java.util包中,Java 中的集合主要有Collection和Map两大接口。
List集合是元素有序并且可以重复的集合;
Set集合是元素无序并且不可以重复的集合;
Map是以键值对(key-value)的形式存储的对象之间的映射,它们都支持泛型。
我们分别介绍了 3 个接口常用的实现类的用法。
这是重点,需要多多进行编码练习。
















