网站首页模块,上海行业网站建设,微信公众号电商网站开发,wordpress禁止google字体在前面的小节中#xff0c;我们学习了数组#xff0c;本小节学习的集合同样用于存放一组数据#xff0c;我们将学习什么是集合、集合的应用场景 #xff0c;在应用场景部分我们将对比 Java 数组与集合的区别#xff0c;还将系统介绍 Java 集合的架构#xff0c;也将结合实…在前面的小节中我们学习了数组本小节学习的集合同样用于存放一组数据我们将学习什么是集合、集合的应用场景 在应用场景部分我们将对比 Java 数组与集合的区别还将系统介绍 Java 集合的架构也将结合实例来讲解集合的实际应用。 1. 什么是集合 在计算机科学中集合是一组可变数量的数据项也可能为 0 个的组合这些数据可能共享某些特征需要以某种操作方式一起进行操作。 Java 中集合主要分为java.util.Collection和java.util.Map两大接口。
下图描绘了 Java 集合的框架 Tips 图表最下方的ArrayList、LinkedList、HashSet以及HashMap都是常用实现类本小节将介绍具体使用。 1.1 Collection
java.util.Collection接口的实现可用于存储 Java 对象。例如学校所有学生可以视为一个Collection。
Collection又可以分为三个子接口分别是
List序列必须按照顺序保存元素因此它是有序的允许重复Queue队列按照排队规则来确定对象产生的顺序有序允许重复Set集不能重复。 1.2 Map
java.util.Map接口的实现可用于表示“键”key和“值”value对象之间的映射。一个映射表示一组“键”对象其中每一个“键”对象都映射到一个“值”对象。因此可以通过键来查找值。例如每一个学生都有他自己的账户积分这个关联关系可以用Map来表示。 2. 集合的应用场景 2.1 数组与集合
在介绍集合的应用场景之前我们先来看看数组和集合的对比。
我们知道数组和集合都用于存放一组数据但数组的容量是固定大小的而集合的容量是动态可变的对于可存放的数据类型数组既可以存放基本数据类型又可以存放引用数据类型而集合只能存放引用数据类型基本数据类型需要转换为对应的包装类才能存放到集合当中。 2.2 集合应用场景
无法预测存储数据的数量由于数组容量是固定大小因此使用集合存储动态数量的数据更为合适同时存储具有一对一关系的数据例如存储学生的积分为了方便检索对应学生的积分可使用Map将学生的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 新增元素
请查看如下实例
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo1 {public static void main(String[] args) {// 实例化一个空列表List 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 处黄色警告 既然IDE有了警告我们就尝试来解决一下将鼠标光标放置到警告处会提示“Unchecked call to ‘add(E)’ as a member of raw type ‘java.util.List’ ”这是IDE的泛型检查可点击Try to generify ArrayListDemo1.java按钮 此时会出现一个Generify的弹窗直接点击Refactor按钮 代码变成了下图所示的样子那 3 处警告被成功消除了 我们观察到代码第 8 行的List类型后面多了一对尖括号“”里面是 Java 的包装类型Integer在ArrayList类型后面也多了一对尖括号这里的中承载的就是 Java 的泛型的类型参数它表示arrayList对象用于存放Integer类型的数据。这样的目的和好处这里不详细展开讨论本小节我们只需知道这样做就可以消除IDEA的警告即可。
由于前面List已经指定了泛型的参数类型为Integer后面的ArrayList就不需要再重复指定了。当然你也可以这样写但是没必要
ListInteger arrayList new ArrayListInteger();同理如果你想向arrayList存放String类型的元素只需将Integer改为String我们再来看一个实例
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo2 {public static void main(String[] args) {// 实例化一个空列表ListString arrayList new ArrayList();// 将字符串元素 Hello 追加到此列表的末尾arrayList.add(Hello);// 将字符串元素 World 追加到此列表的末尾arrayList.add(World);// 打印列表System.out.println(arrayList);// 将字符串元素 Java 插入到此列表中的索引为 1 的位置arrayList.add(1, Java);// 打印列表System.out.println(arrayList);}
}运行结果
[Hello, World]
[Hello, Java, World]代码中首先实例化了一个ArrayList的对象调用了两次add(E e)方法依次向列表尾部插入了Hello和World元素列表中元素为[Hello, World]此时调用add(int index, E element)方法将字符串元素 Java 插入到此列表中的索引为 1 的位置因此列表中的元素为[Hello, Java, World]。
3.3.3 删除元素
请查看如下实例
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo3 {public static void main(String[] args) {// 实例化一个空列表ListString arrayList new ArrayList();// 将字符串元素 Hello 追加到此列表的末尾arrayList.add(Hello);// 将字符串元素 World 追加到此列表的末尾arrayList.add(World);// 将字符串元素 Hello 追加到此列表的末尾arrayList.add(Hello);// 将字符串元素 Java 追加到此列表的末尾arrayList.add(Java);// 打印列表System.out.println(arrayList);// 删除此列表中索引位置为 3 的元素arrayList.remove(3);// 打印列表System.out.println(arrayList);// 删除此列表中第一次出现的 Hello 元素arrayList.remove(Hello);System.out.println(arrayList);}
}运行结果
[Hello, World, Hello, Java]
[Hello, World, Hello]
[World, Hello]代码中我们首先添加了 4 个字符串元素列表内容为[Hello, World, Hello, Java]然后调用remove(int index)方法删除了索引位置为 3 的元素即Java此时列表内容为[Hello, World, Hello] 再次调用remove(Object o)方法删除了列表中第一次出现的Hello元素此时列表内容为[World, Hello]。
3.3.4 修改元素
可使用set()方法修改列表中元素实例如下
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo4 {public static void main(String[] args) {// 实例化一个空列表ListString arrayList new ArrayList();arrayList.add(Hello);// 将字符串元素 World 追加到此列表的末尾arrayList.add(World);// 打印列表System.out.println(arrayList);// 用字符串元素 Hello 替换此列表中索引位置为 1 的元素arrayList.set(1, Java);System.out.println(arrayList);}
}运行结果
[Hello, World]
[Hello, Java]3.3.5 查询元素
可使用get()方法来获取列表中元素实例如下
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo5 {public static void main(String[] args) {// 实例化一个空列表ListString arrayList new ArrayListString();arrayList.add(Hello);arrayList.add(Immoc);for (int i 0; i arrayList.size(); i ) {System.out.println(索引位置 i 的元素为 arrayList.get(i));}}
}运行结果
索引位置0的元素为Hello
索引位置1的元素为Immoc我们在使用for循环遍历列表的时候让限定条件为i arrayList.size();size()方法可获取该列表中元素的数量。
3.2.7 自定义类的常用操作
请查看如下实例
import java.util.ArrayList;
import java.util.List;public class ArrayListDemo6 {static class MybjStudent {private String nickname;private String position;public MybjStudent() {}public MybjStudent(String nickname, String position) {this.setNickname(nickname);this.setPosition(position);}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname nickname;}public String getPosition() {return position;}public void setPosition(String position) {this.position position;}Overridepublic String toString() {return MybjStudent{ nickname nickname \ , position position \ };}}public static void main(String[] args) {// 实例化一个空列表ListMybjStudent arrayList new ArrayList();// 实例化3个学生对象MybjStudent mybjStudent1 new MybjStudent(Colorful, 服务端工程师);MybjStudent mybjStudent2 new MybjStudent(Lillian, 客户端工程师);MybjStudent mybjStudent3 new MybjStudent(小张, 架构师);// 新增元素arrayList.add(mybjStudent1);arrayList.add(mybjStudent2);arrayList.add(mybjStudent3);System.out.println(arrayList);// 删除元素arrayList.remove(mybjStudent2);System.out.println(删除 mybjStudent2 后arrayList 内容为 arrayList);arrayList.remove(1);System.out.println(删除列表中索引位置为 1 的元素后arrayList 内容为 arrayList);// 实例化一个新的学生对象MybjStudent mybjStudent4 new MybjStudent(小李, UI设计师);// 修改元素arrayList.set(0, mybjStudent4);System.out.println(修改后arrayList 内容为 mybjStudent4);// 查询元素将 get() 方法得到的 Object 类型强制转换为 MybjStudent 类型MybjStudent student arrayList.get(0);System.out.println(索引位置 0 的学生的昵称为 student.getNickname());System.out.println(索引位置 0 的学生的职位为 student.getPosition());}
}运行结果
[MybjStudent{nicknameColorful, position服务端工程师}, MybjStudent{nicknameLillian, position客户端工程师}, MybjStudent{nickname小张, position架构师}]
删除 mybjStudent2 后arrayList 内容为[MybjStudent{nicknameColorful, position服务端工程师}, MybjStudent{nickname小张, position架构师}]
删除列表中索引位置为 1 的元素后arrayList 内容为[MybjStudent{nicknameColorful, position服务端工程师}]
修改后arrayList 内容为MybjStudent{nickname小李, positionUI设计师}
索引位置 0 的学生的昵称为小李
索引位置 0 的学生的职位为UI设计师为了方便演示我们定义了一个静态内部类MybjStudent它有两个属性nickname和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否则返回 falseint size()返回该列表中元素的数量Object[] toArray()以正确的顺序从第一个元素到最后一个元素返回一个包含此列表中所有元素的数组。
更多成员方法请翻阅官方文档对于成员方法的使用与ArrayList大同小异这里不再赘述。 4. Set 集合 4.1 概念和特性
Set是元素无序并且不可以重复的集合我们称之为集。Set是Collection的一个子接口它的主要实现类有HashSet、TreeSet、LinkedHashSet、EnumSet等下面我们将详细介绍最常用的HashSet实现类。 4.2 HashSet 实现类
HashSet类依赖于哈希表实际上是HashMap实例下面将会介绍。HashSet中的元素是无序的、散列的。
4.2.1 构造方法
HashSet()构造一个新的空集默认的初始容量为 16最常用负载系数为 0.75HashSet(int initialCapacity)构造一个新的空集 具有指定的初始容量负载系数为 0.75HashSet(int initialCapacity, float loadFactor)构造一个新的空集 支持的 HashMap 实例具有指定的初始容量和指定的负载系数HashSet(Collection? extends E c)构造一个新集合其中包含指定集合中的元素。
4.2.2 常用成员方法
HashSet的常用成员方法如下
boolean add(E e)如果指定的元素尚不存在则将其添加到该集合中boolean contains(Object o)如果此集合包含指定的元素则返回 true否则返回 falseboolean isEmpty()如果此集合不包含任何元素则返回 true否则返回 falseIteratorE iterator()返回此集合中元素的迭代器boolean remove(Object o)从该集合中删除指定的元素如果存在int size()返回此集合中的元素数量。
更多成员方法请翻阅官方文档下面我们将结合实例来介绍以上成员方法的使用。 4.3 实例
4.3.1 新增元素
可使用add()方法向集中添加元素实例如下
import java.util.HashSet;
import java.util.Set;public class HashSetDemo1 {public static void main(String[] args) {// 实例化一个新的空集SetString hashSet new HashSetString();// 向 hashSet 集中依次添加元素Python、Java、PHP、TypeScript、PythonhashSet.add(Python);hashSet.add(Java);hashSet.add(PHP);hashSet.add(TypeScript);hashSet.add(Python);// 打印 hashSet 的内容System.out.println(hashSet中的内容为 hashSet);}
}运行结果
hashSet中的内容为[TypeScript, Java, PHP, Python]在实例中我们先后向hashSet中添加了两次Python元素由于集的元素不可重复特性因此集中只允许出现一个Python元素。我们还观察到打印结果的元素顺序和我们添加的顺序是不同的这验证了集的无序特性。 Tips 由于HashSet的父类AbstractCollection重写了toString()方法因此直接打印集可以直观地展示出集中的元素。 4.3.2 删除元素
可使用remove()方法删除集中元素实例如下
实例演示
import java.util.HashSet;
import java.util.Set;public class HashSetDemo2 {public static void main(String[] args) {// 实例化一个新的空集SetString hashSet new HashSet();// 向 hashSet 集中依次添加元素Python、JavahashSet.add(Python);hashSet.add(Java);// 打印 hashSet 的内容System.out.println(hashSet);// 删除 hashSet 中的 Python 元素hashSet.remove(Python);// 打印 hashSet 的内容System.out.println(删除 Python 元素后hashSet中的内容为 hashSet);}
}运行结果
[Java, Python]
删除 Python 元素后hashSet中的内容为[Java]4.3.3 查询元素
我们知道了ArrayList 通过 get方法来查询元素但HashSet没有提供类似的get方法来查询元素。
这里我们介绍一个迭代器Iterator接口所有的Collection都实现了Iterator接口它可以以统一的方式对各种集合元素进行遍历。我们来看下Iterator接口的常用方法 hasNaxt() 方法检测集合中是否还有下一个元素 next()方法返回集合中的下一个元素 iterator()返回此集合中元素的迭代器。
实例如下
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class HashSetDemo3 {public static void main(String[] args) {// 实例化一个新的空集SetString hashSet new HashSetString();// 向 hashSet 集中依次添加元素Python、Java、PHPhashSet.add(Python);hashSet.add(Java);hashSet.add(PHP);// 打印 hashSet 的内容System.out.println(hashSet);// 获取 hashSet 中元素的迭代器IteratorString iterator hashSet.iterator();System.out.println(迭代器的遍历结果为);while (iterator.hasNext()) {System.out.println(iterator.next());}}
}运行结果
[Java, PHP, Python]
迭代器的遍历结果为
Java
PHP
Python4.3.4 自定义类的常用操作
请查看如下实例
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;public class HashSetDemo4 {/*** 静态内部类学生*/static class MybjStudent {private String nickname;private String position;public MybjStudent() {}public MybjStudent(String nickname, String position) {this.setNickname(nickname);this.setPosition(position);}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname nickname;}public String getPosition() {return position;}public void setPosition(String position) {this.position position;}Overridepublic String toString() {return MybjStudent{ nickname nickname \ , position position \ };}}public static void main(String[] args) {SetMybjStudent hashSet new HashSet();// 实例化3个学生对象MybjStudent mybjStudent1 new MybjStudent(Colorful, 服务端工程师);MybjStudent mybjStudent2 new MybjStudent(Lillian, 客户端工程师);MybjStudent mybjStudent3 new MybjStudent(小张, 架构师);// 新增元素hashSet.add(mybjStudent1);hashSet.add(mybjStudent2);hashSet.add(mybjStudent3);// 使用Iterator遍历hashSetIteratorMybjStudent iterator hashSet.iterator();System.out.println(迭代器的遍历结果为);while (iterator.hasNext()) {System.out.println(iterator.next());}// 查找并删除if (hashSet.contains(mybjStudent1)) {hashSet.remove(mybjStudent1);}System.out.println(删除nickname为Colorful的对象后集合元素为);System.out.println(hashSet);}
}运行结果
迭代器的遍历结果为
MybjStudent{nicknameLillian, position客户端工程师}
MybjStudent{nicknameColorful, position服务端工程师}
MybjStudent{nickname小张, position架构师}
删除nickname为Colorful的对象后集合元素为
[MybjStudent{nicknameLillian, position客户端工程师}, MybjStudent{nicknameColorful, position服务端工程师}, MybjStudent{nickname小张, position架构师}]为了方便演示我们定义了一个静态内部类MybjStudent它有两个属性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()从该映射中删除所有映射SetMap, EntryK, V entrySet返回此映射中包含的映射的集合V get(Object key)返回指定键映射到的值如果该映射不包含键的映射则返回 nullSetK keySet返回此映射中包含的键的结合V put(K key, V value)将指定值与此映射中指定键关联V remove(Object key)如果存在则从此映射中删除指定键的映射。CollectionV values返回此映射中包含的集合。 5.3 实例
下面我们使用 HashMap 来实现一个英汉字典的例子。
实例演示
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;public class HashMapDemo1 {public static void main(String[] args) {MapString, String map new HashMap();// 添加数据map.put(English, 英语);map.put(Chinese, 汉语);map.put(Java, 咖啡);// 打印 mapSystem.out.println(map);// 删除 key 为 Java 的数据map.remove(Chinese);System.out.println(删除键为Chinese的映射后map内容为);// 打印 mapSystem.out.println(map);// 修改元素map.put(Java, 一种编程语言);System.out.println(修改键为Java的值后Java map.get(Java));// 遍历mapSystem.out.println(通过遍历entrySet方法得到 key-value 映射);SetEntryString, String entries map.entrySet();for (EntryString, String entry: entries) {System.out.println(entry.getKey() - entry.getValue());}// 查找集合中键为 English 对应的值SetString keySet map.keySet();for (String key: keySet) {if (key.equals(English)) {System.out.println(English 键对应的值为 map.get(key));break;}}}
}运行结果
{English英语, Java咖啡, Chinese汉语}
删除键为Chinese的映射后map内容为
{English英语, Java咖啡}
修改键为Java的值后Java一种编程语言
通过遍历entrySet方法得到 key-value 映射
English - 英语
Java - 一种编程语言
English 键对应的值为英语实例中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 个接口常用的实现类的用法。同学们要多多进行编码练习。