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是第一次认认真真系统学的语言,一定要系统的全面的学好!
  • 奥里给!!!
  • 没有什么能够阻挡

目标

  1. 什么是集合
  2. 集合的应用场景
  3. 对比 Java 数组与集合的区别
  4. Java 集合的架构
  5. 结合实例来讲解集合的实际应用

1. 什么是集合

在计算机科学中,集合是一组可变数量的数据项(也可能为 0 个)的组合,这些数据可能共享某些特征,需要以某种操作方式一起进行操作。

Java 中集合主要分为​​java.util.Collection​​​和​​java.util.Map​​两大接口。

Java 集合的框架:

强哥说Java--Java集合_List

Tips: 图表最下方的​​ArrayList​​​、​​LinkedList​​​、​​HashSet​​​以及​​HashMap​​都是常用实现类

1.1 Collection

​java.util.Collection​​​接口的实现可用于存储 Java 对象。例如,NBA的所有球员(集合)可以视为一个​​Collection​​(存储类对象)。

​Collection​​又可以分为三个子接口,分别是:

  1. ​List​​:序列,必须按照顺序保存元素,因此它是有序的,允许重复;
  2. ​Queue​​:队列,按照排队规则来确定对象产生的顺序,有序,允许重复;
  3. ​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​​对象:

// 无参构造实例化,初始容量为10
List arrayList1 = new ArrayList();
// 实例化一个初始容量为20的空列表
List arrayList2 = new ArrayList(20);
// 实例化一个集合元素为 arrayList2 的列表(由于 arrayList2 为空列表,因此其实例化的对象也为空列表)
List arrayList3 = new ArrayList(arrayList2);

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 新增元素

package com.caq.oop.demo08;

import java.util.ArrayList;

public class Test {
public static void main(String[] args) {
//实例化一个空列表
ArrayList arrayList = new ArrayList();
for (int i = 0; i < 5; i++) {
//将元素i追加到列表的末尾
arrayList.add(i);
//打印列表
System.out.println(arrayList);
}
}
}

运行结果:

[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]

代码中,首先实例化了一个​​ArrayList​​对象,然后使用 for 循环语句循环 5 次,每次都向​​arrayList​​​对象中追加变量​​i​​,并打印列表内容,运行结果清晰的展示了每次新增元素的过程。

Tips:由于​​ArrayList​​​的父类​​AbstractCollection​​​重写了​​toString()​​方法,因此直接打印列表,可以直观地展示出列表中的元素。

3.3.2 泛型初识

Tips:泛型(​​Genericity​​)

介绍一下泛型以及其使用方法。

如果你使用​​IDEA​​编写如上代码,将会有下图所示的 3 处黄色警告:

强哥说Java--Java集合_算法_02

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

强哥说Java--Java集合_List_03

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

强哥说Java--Java集合_面试_04

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

强哥说Java--Java集合_List_05

​List​​​类型后面多了一对尖括号“​​<>​​​”,​​<>​​​里面是 Java 的包装类型​​Integer​​​,在​​ArrayList​​​类型后面也多了一对尖括号,这里的​​<>​​​中承载的就是 Java 的泛型的类型参数,它表示​​arrayList​​​对象用于存放​​Integer​​类型的数据。

我们只需知道这样做就可以消除​​IDEA​​的警告即可。后面会继续深入!

由于前面​​List​​​已经指定了泛型的参数类型为​​Integer​​​,后面的​​ArrayList​​就不需要再重复指定了。当然你也可以这样写(但是没必要):

List<Integer> arrayList = new ArrayList<Integer>();

同理,如果你想向​​arrayList​​​存放​​String​​​类型的元素,只需将​​<Integer>​​​改为​​<String>​​,我们再来看一个实例:

实例演示

package com.caq.oop.demo08;

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {
//实例化一个空列表
List<String> arrayList = new ArrayList<>();
//将Hello打印到arrayList列表的末尾
arrayList.add("Hello");
arrayList.add("Hello");
//打印列表
System.out.println(arrayList);
//将字符串元素Monkey插入到此列表中的索引为1的位置
arrayList.add(1, "Monkey");
}
}

强哥说Java--Java集合_算法_06

两种形式,直接最后添加字符换或者指定索引添加,IDEA这点做的还是挺好的!!!

[Hello, Hello]
[Hello, Monkey, Hello]

代码中,首先实例化了一个​​ArrayList​​​的对象,调用了两次​​add(E e)​​​方法,依次向列表尾部插入了​​Hello​​​和​​World​​​元素,列表中元素为​​[Hello, World]​​​,此时调用​​add(int index, E element)​​​方法,将字符串元素 Java 插入到此列表中的索引为 1 的位置,因此列表中的元素为​​[Hello, Java, World]​​。

3.3.3 删除元素

实例演示

package com.caq.oop.demo08;

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {
//实例化一个空列表
List<String> arrayList = new ArrayList<>();
//将Hello打印到arrayList列表的末尾
arrayList.add("Hello");
arrayList.add("Hello");
arrayList.add("Hello");
arrayList.add("Tiger");
//打印列表
System.out.println(arrayList);
//删除索引为3的元素
arrayList.remove(3);
//打印列表
System.out.println(arrayList);

//删除列表第一次出现的Hello元素
arrayList.remove("Hello");
System.out.println(arrayList);

}
}

运行结果:

[Hello, Hello, Hello, Tiger]
[Hello, Hello, Hello]
[Hello, Hello]

代码中,我们首先添加了 4 个字符串元素,列表内容为​​[Hello, World, Hello, Java]​​​,然后调用​​remove(int index)​​​方法删除了索引位置为 3 的元素(即​​Java​​​),此时列表内容为​​[Hello, World, Hello]​​​ ,再次调用​​remove(Object o)​​​方法,删除了列表中第一次出现的​​Hello​​​元素,此时列表内容为​​[World, Hello]​​。

奥里给!!!!

3.3.4 修改元素

可使用​​set()​​方法修改列表中元素,实例如下:

实例演示

package com.caq.oop.demo08;

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {
//实例化一个空列表
List<String> arrayList = new ArrayList<>();
arrayList.add("Hello!");
arrayList.add("Hello!");
//打印
System.out.println(arrayList);
//用字符串元素Hello替换列表索引位置为1的元素
arrayList.set(1,"Monkey");
System.out.println(arrayList);

}
}

运行结果:

[Hello!, Hello!]
[Hello!, Monkey]

3.3.5 查询元素

可使用​​get()​​方法来获取列表中元素,实例如下:

实例演示

package com.caq.oop.demo08;

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {
//实例化一个空列表
List<String> arrayList = new ArrayList<>();
arrayList.add("Hello0");
arrayList.add("Hello1");
//用get方法查询索引为1的元素
for (int i = 0; i < arrayList.size(); i++) {
System.out.println("索引为" + i + "元素为:" + arrayList.get(i));
}
}
}

运行结果:

索引为0元素为:Hello0
索引为1元素为:Hello1

我们在使用​​for​​​循环遍历列表的时候,让限定条件为​​i < arrayList.size();​​​,​​size()​​方法可获取该列表中元素的数量

3.2.7 自定义类的常用操作

请查看如下实例:

实例演示

package com.caq.oop.demo08;
/*
当我们打印一个对象的引用时,实际是默认调用这个对象的toString()方法

当打印的对象所在类没有重写Object中的toString()方法时,默认调用的是Object类中toString()方法。

返回此对象所在的类及对应的堆空间对象实体的首地址值

当我们打印对象所在类重写了toString(),调用的就是已经重写了的toString()方法,一般重写是将类对象的属性信息返回。

toString 方法会在 println 的时候被自动调用.
将对象转成字符串这样的操作我们称为 序列化.
toString 是 Object 类提供的方法, 我们自己创建的 Person 类默认继承自 Object 类, 可以重写 toString 方法实 现我们自己版本的转换字符串方法

*/

//自定义类需要重写toString方法,通过字符串的方式显示对象
import java.util.ArrayList;
import java.util.List;

public class Test {
static class NBA {
private String name;

private String position;

public NBA(String name, String position) {
= name;
this.position = position;
}

public String getName() {
return name;
}

public void setName(String name) {
= name;
}

public String getPosition() {
return position;
}

public void setPosition(String position) {
this.position = position;
}

@Override
public String toString() {
return "NBA{" +
"name='" + name + '\'' +
", position='" + position + '\'' +
'}';
}

public static void main(String[] args) {
//实例化一个空列表
List<NBA> arrayList = new ArrayList<>();
//实例化3个NBA对象
NBA nba1 = new NBA("乔丹","得分后卫SG");
NBA nba2 = new NBA("詹姆斯","小前锋SF");
NBA nba3 = new NBA("库里","控球后卫PG");

//新增元素
arrayList.add(nba1);
arrayList.add(nba2);
arrayList.add(nba3);
System.out.println(arrayList);

//删除元素
arrayList.remove(nba3);
System.out.println("删除后的动态数组arraylist为:"+arrayList);
arrayList.remove(1);
System.out.println("删除后的动态数组索引为1的元素arraylist为:"+arrayList);

//修改元素
NBA nba4 = new NBA("格里芬","大前锋PF");
arrayList.set(0,nba4);
//查询元素,将get()方法得到的object类强制转化为NBA类型
NBA player = arrayList.get(0);
System.out.println("索引为0的球员昵称为:"+player.getName());
System.out.println("索引为0的球员位置为:"+player.getPosition());
}

}
}

运行结果:

[NBA{name='乔丹', position='得分后卫SG'}, NBA{name='詹姆斯', position='小前锋SF'}, NBA{name='库里', position='控球后卫PG'}]
删除后的动态数组arraylist为:[NBA{name='乔丹', position='得分后卫SG'}, NBA{name='詹姆斯', position='小前锋SF'}]
删除后的动态数组索引为1的元素arraylist为:[NBA{name='乔丹', position='得分后卫SG'}]
索引为0的球员昵称为:格里芬
索引为0的球员位置为:大前锋PF

为了方便演示,我们定义了一个静态内部类​​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 新增元素

实例演示

package com.caq.oop.demo08;

import java.util.Set;
import java.util.HashSet;

public class Test {
public static void main(String[] args) {
//实例化一个新的空集
Set<String> hashSet = new HashSet<>();
//向hashSet集中依次添加元素
hashSet.add("Monkey");
hashSet.add("Monkey");
hashSet.add("Tiger");
hashSet.add("Dog");
hashSet.add("Cat");
// 打印 hashSet 的内容
System.out.println("hashSet中的内容为:" + hashSet);
}
}

运行结果:

hashSet中的内容为:[Monkey, Cat, Dog, Tiger]

在实例中,我们先后向​​hashSet​​​中添加了两次​​Monkey​​元素,由于集的元素不可重复特性,因此集中只允许出现一个​​Monkey​​元素。我们还观察到,打印结果的元素顺序和我们添加的顺序是不同的,这验证了集的无序特性

Tips: 由于​​HashSet​​​的父类​​AbstractCollection​​​重写了​​toString()​​方法,因此直接打印集,可以直观地展示出集中的元素。

4.3.2 删除元素

可使用​​remove()​​方法删除集中元素

实例演示

package com.caq.oop.demo08;

import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;

public class Test {
public static void main(String[] args) {
//实例化一个新的空集
Set<String> hashSet = new HashSet<>();
//向hashSet集中依次添加元素
hashSet.add("Monkey");
hashSet.add("Monkey");
hashSet.add("Tiger");
hashSet.add("Dog");
hashSet.add("Cat");
System.out.println("hashSet中的内容为:" + hashSet);

hashSet.remove("Cat");
System.out.println("hashSet中的内容为:" + hashSet);
}
}

运行结果:

hashSet中的内容为:[Monkey, Cat, Dog, Tiger]
hashSet中的内容为:[Monkey, Dog, Tiger]

4.3.3 查询元素

我们知道了​​ArrayList​​​ 通过 ​​get​​​方法来查询元素,但​​HashSet​​​没有提供类似的​​get​​方法来查询元素。

这里我们介绍一个迭代器(​​Iterator​​​)接口,所有的​​Collection​​​都实现了​​Iterator​​​接口,它可以以统一的方式对各种集合元素进行遍历。我们来看下​​Iterator​​接口的常用方法:

  • ​hasNaxt()​​ 方法检测集合中是否还有下一个元素;
  • ​next()​​方法返回集合中的下一个元素;
  • ​iterator()​​:返回此集合中元素的迭代器。

实例如下:

实例演示

package com.caq.oop.demo08;

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

public class Test {
public static void main(String[] args) {
//实例化一个新的空集
Set<String> hashSet = new HashSet<>();
//向hashSet集中依次添加元素
hashSet.add("Monkey");
hashSet.add("Tiger");
hashSet.add("Dog");
hashSet.add("Cat");
System.out.println("hashSet中的内容为:" + hashSet);

//获取hashSet中元素的迭代器
Iterator<String> iterator = hashSet.iterator();
System.out.println("迭代器的遍历结果为:");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}

运行结果:

hashSet中的内容为:[Monkey, Cat, Dog, Tiger]
迭代器的遍历结果为:
Monkey
Cat
Dog
Tiger

4.3.4 自定义类的常用操作

请查看如下实例:

实例演示

package com.caq.oop.demo08;

import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;

public class Test {

static class NBA{
private String name;
private String positon;

public NBA(String name, String positon) {
= name;
this.positon = positon;
}

public String getName() {
return name;
}

public void setName(String name) {
= name;
}

public String getPositon() {
return positon;
}

public void setPositon(String positon) {
this.positon = positon;
}

@Override
public String toString() {
return "NBA{" +
"name='" + name + '\'' +
", positon='" + positon + '\'' +
'}';
}

public static void main(String[] args) {
Set<NBA> hashSet = new HashSet<>();
//实例化三个NBA对象
NBA nba1 = new NBA("Kobe","SG");
NBA nba2 = new NBA("LBJ", "SF");
NBA nba3 = new NBA("Pual", "PG");


//新增元素
hashSet.add(nba1);
hashSet.add(nba2);
hashSet.add(nba3);

//使用Iterator遍历hashSet
Iterator<NBA> iterator = hashSet.iterator();
System.out.println("迭代器的遍历结果为:");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}

//查找并删除
if (hashSet.contains(nba1)){
hashSet.remove(nba1);
}
System.out.println("删除name为Kobe的对象后,集合元素为:");
System.out.println(hashSet);
}

}
}

运行结果:

迭代器的遍历结果为:
NBA{name='Pual', positon='PG'}
NBA{name='LBJ', positon='SF'}
NBA{name='Kobe', positon='SG'}
删除name为Kobe的对象后,集合元素为:
[NBA{name='Pual', positon='PG'}, NBA{name='LBJ', positon='SF'}]

为了方便演示,我们定义了一个静态内部类​​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​​ 来实现一个英汉字典的例子。

实例演示

package com.caq.oop.demo08;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
//添加数据
map.put("Monkey", "猴子");
map.put("Tiger", "老虎");
map.put("Rabbit", "兔子");

//打印map
System.out.println(map);

//删除key为monkey的数据
map.remove("Monkey");
System.out.println("删除键为Monkey的映射后,map内容为:");
System.out.println(map);

//修改元素
map.put("Tiger", "老鼠");
System.out.println("修改键为Tiger的值后,Tiger=" + map.get("Tiger"));

// 遍历map
System.out.println("通过遍历entrySet方法得到 key-value 映射:");
Set<Entry<String, String>> test = map.entrySet();
for (Entry<String, String> entry : test) {
System.out.println(entry.getKey() + "-" + entry.getValue());
}

// 查找集合中键为 Rabbit 对应的值
Set<String> keySet = map.keySet();
for (String key : keySet) {
if (key.equals("Rabbit")) {
System.out.println("Rabbit 键对应的值为:" + map.get(key));
break;
}
}
}
}

运行结果:

{Monkey=猴子, Rabbit=兔子, Tiger=老虎}
删除键为Monkey的映射后,map内容为:
{Rabbit=兔子, Tiger=老虎}
修改键为Tiger的值后,Tiger=老鼠
通过遍历entrySet方法得到 key-value 映射:
Rabbit-兔子
Tiger-老鼠
Rabbit 键对应的值为:兔子

实例中,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 个接口常用的实现类的用法。

这是重点,需要多多进行编码练习。