第十章 集合类 总结
10.1集合类概述
为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java 提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。Java 所有的集合类都位于 java.util 包下,提供了一个表示和操作对象集合的统一构架,包含大量集合接口,以及这些接口的实现类和操作它们的算法。
集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量),而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。
Java 集合类型分为 Collection 和 Map,它们是 Java 集合的根接口,这两个接口又包含了一些子接口或实现类。。
对于 Set、List、Queue 和 Map 这 4 种集合,Java 最常用的实现类分别是 HashSet、TreeSet、ArrayList、ArrayDueue、LinkedList 和 HashMap、TreeMap 等。表 2 介绍了集合中这些常用的实现类。
10.2Collection接口
Collection 接口是 List、Set 和 Queue 接口的父接口,通常情况下不被直接使用。Collection 接口定义了一些通用的方法,通过这些方法可以实现对集合的基本操作。定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 合。
注意:以上方法完全来自于 Java API 文档,读者可自行参考 API 文档来查阅这些方法的详细信息。读者无需硬性记忆这些方法,可以和实际生活结合记忆。集合类就像容器,现实生活中容器的功能,就是添加对象、删除对象、清空容器和判断容器是否为空等,集合类为这些功能都提供了对应的方法。
public static void main(String[] args) {//主方法ArrayList list1 = new ArrayList(); // 创建集合 list1ArrayList list2 = new ArrayList(); // 创建集合 list2list1.add("one"); // 向 list1 添加一个元素list1.add("two"); // 向 list1 添加一个元素list2.addAll(list1); // 将 list1 的所有元素添加到 list2list2.add("three"); // 向 list2 添加一个元素System.out.println("list2 集合中的元素如下:");//输出内容Iterator it1 = list2.iterator();//创建迭代器while (it1.hasNext()) {//while循环输出所有元素System.out.print(it1.next() + "、");//输出语句}
}
运行结果:
public static void main(String[] args) {ArrayList list1 = new ArrayList(); // 创建集合 list1ArrayList list2 = new ArrayList(); // 创建集合 list2list1.add("one");list1.add("two");list1.add("three");System.out.println("list1 集合中的元素数量:" + list1.size()); // 输出list1中的元素数量list2.add("two");list2.add("four");list2.add("six");System.out.println("list2 集合中的元素数量:" + list2.size()); // 输出list2中的元素数量list2.remove(2); // 删除第 3 个元素System.out.println("\nremoveAll() 方法之后 list2 集合中的元素数量:" + list2.size());System.out.println("list2 集合中的元素如下:");Iterator it1 = list2.iterator();while (it1.hasNext()) {System.out.print(it1.next() + "、");}list1.removeAll(list2);System.out.println("\nremoveAll() 方法之后 list1 集合中的元素数量:" + list1.size());System.out.println("list1 集合中的元素如下:");Iterator it2 = list1.iterator();while (it2.hasNext()) {System.out.print(it2.next() + "、");
运行结果如下:
注意:retainAll( ) 方法的作用与 removeAll( ) 方法相反,即保留两个集合中相同的元素,其他全部删除
10.3List集合
List 是一个有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List 集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List 集合默认按元素的添加顺序设置元素的索引,第一个添加到 List 集合中的元素的索引为 0,第二个为 1,依此类推。
10.3.1List接口
10.3.2List接口的实现类
注意:当调用 List 的 set(int index, Object element) 方法来改变 List 集合指定索引处的元素时,指定的索引必须是 List 集合的有效索引。例如集合长度为 4,就不能指定替换索引为 4 处的元素,也就是说这个方法不会改变 List 集合的长度。
public class Test {public static void main(String[] args) {Product pd1 = new Product(4, "木糖醇", 10);Product pd2 = new Product(5, "洗发水", 12);Product pd3 = new Product(3, "热水壶", 49);List list = new ArrayList(); // 创建集合list.add(pd1);list.add(pd2);list.add(pd3);System.out.println("*************** 商品信息 ***************");for (int i = 0; i < list.size(); i++) {// 循环遍历集合,输出集合元素Product product = (Product) list.get(i);System.out.println(product);}
运行结果如下:
public static void main(String[] args) {List list = new ArrayList();list.add("One");list.add("|");list.add("Two");list.add("|");list.add("Three");list.add("|");list.add("Four");System.out.println("list 集合中的元素数量:" + list.size());System.out.println("list 集合中的元素如下:");Iterator it = list.iterator();while (it.hasNext()) {System.out.print(it.next() + "、");}System.out.println("\n在 list 集合中'丨'第一次出现的位置是:" + list.indexOf("|"));System.out.println("在 list 集合中'丨'最后一次出现的位置是:" + list.lastIndexOf("|")); }
运行结果如下:
public static void main(String[] args) {List list = new ArrayList();list.add("One");list.add("Two");list.add("Three");list.add("Four");list.add("Five");list.add("Six");list.add("Seven");System.out.println("list 集合中的元素数量:" + list.size());System.out.println("list 集合中的元素如下:");Iterator it = list.iterator();while (it.hasNext()) {System.out.print(it.next() + "、");}List sublist = new ArrayList();sublist = list.subList(2, 5); // 从list集合中截取索引2~5的元素,保存到sublist集合中System.out.println("\nsublist 集合中元素数量:" + sublist.size());System.out.println("sublist 集合中的元素如下:");it = sublist.iterator();while (it.hasNext()) {System.out.print(it.next() + "、");} }
运行结果如下:
10.3.3Iterator
public class Test {public static void main(String[] args) {LinkedList<String> products = new LinkedList<String>(); // 创建集合对象String p1 = new String("六角螺母");String p2 = new String("10A 电缆线");String p3 = new String("5M 卷尺");String p4 = new String("4CM 原木方板");products.add(p1); // 将 p1 对象添加到 LinkedList 集合中products.add(p2); // 将 p2 对象添加到 LinkedList 集合中products.add(p3); // 将 p3 对象添加到 LinkedList 集合中products.add(p4); // 将 p4 对象添加到 LinkedList 集合中String p5 = new String("标准文件夹小柜");products.addLast(p5); // 向集合的末尾添加p5对象System.out.print("*************** 商品信息 ***************");System.out.println("\n目前商品有:");for (int i = 0; i < products.size(); i++) {System.out.print(products.get(i) + "\t");}System.out.println("\n第一个商品的名称为:" + products.getFirst());System.out.println("最后一个商品的名称为:" + products.getLast());products.removeLast(); // 删除最后一个元素System.out.println("删除最后的元素,目前商品有:");for (int i = 0; i < products.size(); i++) {System.out.print(products.get(i) + "\t");}
运行结果如下:
10.4Set集合
Set 集合类似于一个罐子,程序可以依次把多个对象“丢进”Set 集合,而 Set 集合通常不能记住元素的添加顺序。也就是说 Set 集合中的对象不按特定的方式排序,只是简单地把对象加入集合。Set 集合中不能包含重复的对象,并且最多只允许包含一个 null 元素。
10.4.1Set接口
HashSet 具有以下特点:
不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
HashSet 不是同步的,如果多个线程同时访问或修改一个 HashSet,则必须通过代码来保证其同步。
集合元素值可以是 null。当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的 hashCode 值,然后根据该 hashCode 值决定该对象在 HashSet 中的存储位置。如果有两个元素通过 equals() 方法比较返回的结果为 true,但它们的 hashCode 不相等,HashSet 将会把它们存储在不同的位置,依然可以添加成功。
也就是说,两个对象的 hashCode 值相等且通过 equals() 方法比较返回结果为 true,则 HashSet 集合认为两个元素相等。
在 HashSet 类中实现了 Collection 接口中的所有方法。HashSet 类的常用构造方法重载形式如下。
HashSet():构造一个新的空的 Set 集合。
HashSet(Collection<? extends E>c):构造一个包含指定 Collection 集合元素的新 Set 集合。其中,“< >”中的 extends 表示 HashSet 的父类,即指明该 Set 集合中存放的集合元素类型。c 表示其中的元素将被存放在此 Set 集合中。public static void main(String[] args) {HashSet<String> courseSet = new HashSet<String>(); // 创建一个空的 Set 集合String course1 = new String("Java入门教程");String course2 = new String("Python基础教程");String course3 = new String("C语言学习教程");String course4 = new String("Golang入门教程");courseSet.add(course1); // 将 course1 存储到 Set 集合中courseSet.add(course2); // 将 course2 存储到 Set 集合中courseSet.add(course3); // 将 course3 存储到 Set 集合中courseSet.add(course4); // 将 course4 存储到 Set 集合中System.out.println("C语言中文网教程有:");Iterator<String> it = courseSet.iterator();while (it.hasNext()) {System.out.println("《" + (String) it.next() + "》"); // 输出 Set 集合中的元素}System.out.println("有" + courseSet.size() + "套精彩教程!"); }
运行结果如下:
、
注意:在以上示例中,如果再向 CourseSet 集合中再添加一个名称为“Java入门教程”的 String 对象,则输出的结果与上述执行结果相同。也就是说,如果向 Set 集合中添加两个相同的元素,则后添加的会覆盖前面添加的元素,即在 Set 集合中不会出现相同的元素。
10.4.2Set接口的实现类
public class Test08 {public static void main(String[] args) {TreeSet<Double> scores = new TreeSet<Double>(); // 创建 TreeSet 集合Scanner input = new Scanner(System.in);System.out.println("------------学生成绩管理系统-------------");for (int i = 0; i < 5; i++) {System.out.println("第" + (i + 1) + "个学生成绩:");double score = input.nextDouble();// 将学生成绩转换为Double类型,添加到TreeSet集合中scores.add(Double.valueOf(score));}Iterator<Double> it = scores.iterator(); // 创建 Iterator 对象System.out.println("学生成绩从低到高的排序为:");while (it.hasNext()) {System.out.print(it.next() + "\t");}System.out.println("\n请输入要查询的成绩:");double searchScore = input.nextDouble();if (scores.contains(searchScore)) {System.out.println("成绩为: " + searchScore + " 的学生存在!");} else {System.out.println("成绩为: " + searchScore + " 的学生不存在!");}// 查询不及格的学生成绩SortedSet<Double> score1 = scores.headSet(60.0);System.out.println("\n不及格的成绩有:");for (int i = 0; i < score1.toArray().length; i++) {System.out.print(score1.toArray()[i] + "\t");}// 查询90分以上的学生成绩SortedSet<Double> score2 = scores.tailSet(90.0);System.out.println("\n90 分以上的成绩有:");for (int i = 0; i < score2.toArray().length; i++) {System.out.print(score2.toArray()[i] + "\t");}} }
运行结果如下:
注意:在使用自然排序时只能向 TreeSet 集合中添加相同数据类型的对象,否则会抛出 ClassCastException 异常。如果向 TreeSet 集合中添加了一个 Double 类型的对象,则后面只能添加 Double 对象,不能再添加其他类型的对象,例如 String 对象等。
10.5Map集合
Map 是一种键-值对(key-value)集合,Map 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据。
Map 集合里保存着两组值,一组值用于保存 Map 里的 key,另外一组值用于保存 Map 里的 value,key 和 value 都可以是任何引用类型的数据。Map 的 key 不允许重复,value 可以重复,即同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false。
Map 中的 key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。从 Map 中取出数据时,只要给出指定的 key,就可以取出对应的 value。
Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中,HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序。
10.5.1Map接口
Map 集合最典型的用法就是成对地添加、删除 key-value 对,接下来即可判断该 Map 中是否包含指定 key,也可以通过 Map 提供的 keySet() 方法获取所有 key 组成的集合,进而遍历 Map 中所有的 key-value 对。下面程序示范了 Map 的基本功能。
10.5.2Map接口的实现类
Map接口常用的实现类有HashMap和TreeMap两种,分别如下。
(1)HashMap类是基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。HashMap通过哈希表对其内部的映射关系进行快速查找、此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
(2)TreeMap类不仅实现了Map接口,还实现了java、uili、SortedMap接口,因此,集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap类比HashMap类性能稍差。由于TreeMap类实现的Map集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null.
import java.util.*;public class UseHashMap {public static void main(String[] args) {Map<String, String> map = new HashMap<>(); // 创建Map实例map.put("ISBN-978654", "Java从入门到精通"); // 向集合中添加对象map.put("ISBN-978361", "Android从入门到精通");map.put("ISBN-978893", "21天学Android");map.put("ISBN-978756", "21天学Java");Set<String> set = map.keySet(); // 构建Map集合中所有key对象的集合Iterator<String> it = set.iterator(); // 创建集合迭代器System.out.println("key值:");while (it.hasNext()) { // 遍历集合System.out.print(it.next()+"\t");}Collection<String> coll = map.values(); // 构建Map集合中所有values值集合it = coll.iterator();System.out.println("\nvalues值:");while (it.hasNext()) { // 遍历集合System.out.print(it.next()+"\t");}}
}
运行结果如下:
public class Test09 {public static void main(String[] args) {HashMap users = new HashMap();users.put("11", "张浩太"); // 将学生信息键值对存储到Map中users.put("22", "刘思诚");users.put("33", "王强文");users.put("44", "李国量");users.put("55", "王路路");System.out.println("******** 学生列表 ********");Iterator it = users.keySet().iterator();while (it.hasNext()) {// 遍历 MapObject key = it.next();Object val = users.get(key);System.out.println("学号:" + key + ",姓名:" + val);}Scanner input = new Scanner(System.in);System.out.println("请输入要删除的学号:");int num = input.nextInt();if (users.containsKey(String.valueOf(num))) { // 判断是否包含指定键users.remove(String.valueOf(num)); // 如果包含就删除} else {System.out.println("该学生不存在!");}System.out.println("******** 学生列表 ********");it = users.keySet().iterator();while (it.hasNext()) {Object key = it.next();Object val = users.get(key);System.out.println("学号:" + key + ",姓名:" + val);}}
}
运行结果如下:
TreeMap 类的使用方法与 HashMap 类相同,唯一不同的是 TreeMap 类可以对键对象进行排序。
10.6集合的使用场合
Map 集合的遍历与 List 和 Set 集合不同。Map 有两组值,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。Map 以及实现 Map 的接口类(如 HashMap、TreeMap、LinkedHashMap、Hashtable 等)都可以用以下几种方式遍历。
1)在 for 循环中使用 entries 实现 Map 的遍历(最常见和最常用的)。
public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("Java入门教程", "http://c.biancheng.net/java/");map.put("C语言入门教程", "http://c.biancheng.net/c/");for (Map.Entry<String, String> entry : map.entrySet()) {String mapKey = entry.getKey();String mapValue = entry.getValue();System.out.println(mapKey + ":" + mapValue);}
}
2)使用 for-each 循环遍历 key 或者 values,一般适用于只需要 Map 中的 key 或者 value 时使用。性能上比 entrySet 较好。
Map<String, String> map = new HashMap<String, String>();
map.put("Java入门教程", "http://c.biancheng.net/java/");
map.put("C语言入门教程", "http://c.biancheng.net/c/");
// 打印键集合
for (String key : map.keySet()) {System.out.println(key);
}
// 打印值集合
for (String value : map.values()) {System.out.println(value);
}
3)使用迭代器(Iterator)遍历
Map<String, String> map = new HashMap<String, String>();
map.put("Java入门教程", "http://c.biancheng.net/java/");
map.put("C语言入门教程", "http://c.biancheng.net/c/");
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while (entries.hasNext()) {Entry<String, String> entry = entries.next();String key = entry.getKey();String value = entry.getValue();System.out.println(key + ":" + value);
}
4)通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作。
for(String key : map.keySet()){String value = map.get(key);System.out.println(key+":"+value);
}
前面介绍了Java中最常见的3种集合:List集合、Set集合和Map集合,那么在实际开发中,具体何时应该选择哪种集合呢?这里我们总结了以下原则。
(1) List集合关注的是索引,其元素是顺序存放的,例如一个班的学生成绩,成绩可以重复,就可以使用List集合存取,
(2) Set集合关注唯一性,它的值不允许重复,例如每个班的学生的学号,每个学生的学号是不能重复的.
(3) Map集合关注的是唯一的标识符(KEY),它将唯一的键映射到某个元素,例如每个班学生的学号与姓名的映射,每个学号对应一个学生的姓名,学号是不能重复的,但是学生的姓名有可能重复。
第十章 集合类 总结相关推荐
- JAVA SE基础笔记
第一天 JDK安装.快捷键.JAVA语言特点 1.Java语言的概述 1.1 Java语言的背景 Java语言诞生于1995年,在编程语言排行榜占据重要的地位. Java语言之父是高斯林,以前隶属于 ...
- Java第十章总结集合类
10.1集合类概述 为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java 提供了集合类.集合类主要负责保存.盛装其他数据,因此集合类也被称为容器类.Java 所有的集合类 ...
- 【哈工大软件构造】学习笔记10 第十章、第十一章、第十二章
目录 第十章 面向可维护性的构造技术 1 软件维护和演化 2 可维护性的度量 3 模块化设计和模块性准则 模块划分的五个准则 模块设计的五个原则 耦合度和聚合度 4 OO设计准则:SOLID SRP ...
- Java 第十章.泛型
Java 第十章.泛型 1.为什么要有泛型 2.在集合中使用泛型 3.自定义泛型结构 3.1使用 3.2注意点 3.3泛型方法 3.4泛型方法的使用情景 4.泛型在继承上的体现 5.通配符的使用 5. ...
- java常用的集合对象_java常用实体类、集合类
java常用实体类.集合类 [转自51cto博客jichangwei的BLOG] 1:String类,字符串是常量,他们的值在创建之后不能更改,可以共享. equals()用来比较两个字符串的值,== ...
- 获取后台集合并遍历_java集合类汇总,终于出总结了,再也不用担心混淆了
一:集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...
- 数字图像处理——第十章 图像分割
数字图像处理--第十章 图像分割 文章目录 数字图像处理--第十章 图像分割 写在前面 1 点.线和边缘检测 1.1 孤立点的检测 1.2 线检测 1.3 边缘检测 2 阈值处理 2.1 单一全局阈值 ...
- C#的6种常用集合类大比拼【月儿原创】
C#的6种常用集合类大比拼 作者:清清月儿 主页:http://blog.csdn.net/21aspnet/ 时间:2007.6.27 说明:MSDN没有说出几种集合类其间的区别 ...
- 通过C#实现集合类纵览.NET Collections及相关技术
概述:在真正的对象化开发项目中,我们通常会将常用的业务实体抽象为特定的类,如Employee.Customer.Contact等,而多数的类之间会存在着相应的关联或依存关系,如Employee和Cus ...
最新文章
- $_SERVER['SCRIPT_FILENAME'] 与 __FILE__ 区别
- 中国鱼胶原蛋白行业应用前景与十四五投资建议报告2022年
- 重写StyleSheetTheme
- Lomsat gelral
- 新疆大学OJ(ACM) 1099: 数列有序!
- HttpModule HttpHandler(转)
- Hibernate与mybatis比较
- android gsm编程,Android新手入门 FAQ
- Altium Designer 17 安装方法及步骤
- 安卓机型app的编译与反编译 apk文件的简单说明与解析
- 【数值计算】计算机中的数值计算
- 短期出差北京个人所见所闻所感
- 输入 10 个学生 3 门课的成绩,用函数实现:找出最高的分数所对应的学号和成绩
- 华为MateBook E 12.6英寸 win11 16g+512g 轻评测
- STM32-SWD仿真时PB3,PB4,PA15使用问题
- idea 上传项目到码云git仓库提交到gitee(完整操作流程)
- 基于html篮球网页游戏,分享一款在线打篮球游戏网页源码
- vue 首页白屏优化
- 萨克斯的最佳清洁办法
- Hyper-V虚拟机启动出现黑屏光标闪动