10.1集合类概述

为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java 提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。Java 所有的集合类都位于 java.util 包下,提供了一个表示和操作对象集合的统一构架,包含大量集合接口,以及这些接口的实现类和操作它们的算法。

集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量),而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。

Java 集合类型分为 Collection 和 Map,它们是 Java 集合的根接口,这两个接口又包含了一些子接口或实现类。图 1 和图 2 分别为 Collection 和 Map 的子接口及其实现类。

对于 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(); // 创建集合 list1
    ArrayList list2 = new ArrayList(); // 创建集合 list2
    list1.add("one"); // 向 list1 添加一个元素
    list1.add("two"); // 向 list1 添加一个元素
    list2.addAll(list1); // 将 list1 的所有元素添加到 list2
    list2.add("three"); // 向 list2 添加一个元素
    System.out.println("list2 集合中的元素如下:");
    Iterator it1 = list2.iterator();
    while (it1.hasNext()) {
        System.out.print(it1.next() + "、");
    }
}

public static void main(String[] args) {
    ArrayList list1 = new ArrayList(); // 创建集合 list1
    ArrayList list2 = new ArrayList(); // 创建集合 list2
    list1.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接口的实现类

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()) {
            // 遍历 Map
            Object 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第十章总结集合类相关推荐

  1. Java 第十章.泛型

    Java 第十章.泛型 1.为什么要有泛型 2.在集合中使用泛型 3.自定义泛型结构 3.1使用 3.2注意点 3.3泛型方法 3.4泛型方法的使用情景 4.泛型在继承上的体现 5.通配符的使用 5. ...

  2. java泛型实验报告,java实验报告异常集合类和泛型

    java实验报告异常集合类和泛型 成绩: 面向对象原理与 Java 实践课程实验报告实验 3:异常.集合类和泛型姓 名 _ ___ 班 级 _ ___ 学 号 _ ___ 实验地点 _ ___ 实验时 ...

  3. 速学堂(java)第十章编程题答案(自写)

    速学堂(java)第十章编程题答案(自写) 1. 实现字节数组和任何基本类型和引用类型执行的相互转换 提示:使用ByteArrayInutStream和ByteArrayOutputStream. p ...

  4. Java工程师成神之路java基础知识之集合类(二)

    Java 8中Map相关的红黑树的引用背景.原理等 HashMap的容量.扩容 很多人在通过阅读源码的方式学习Java,这是个很好的方式.而JDK的源码自然是首选.在JDK的众多类中,我觉得HashM ...

  5. 【Java中常用的集合类】

    1.Java中集合框架图 2.List 和 Set 的区别? List , Set 都是继承自Collection 接口 List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重 ...

  6. java 集合 介绍_java集合类基本简介

    java集合类基本简介 序号 类描述 1 AbstractCollection 实现了大部分的集合接口. 2 AbstractList 继承于AbstractCollection 并且实现了大部分Li ...

  7. java 合并 set_【Java必修课】各种集合类的合并(数组、List、Set、Map)

    1 介绍 集合类可谓是学习必知.编程必用.面试必会的,而且集合的操作十分重要:本文主要讲解如何合并集合类,如合并两个数组,合并两个List等.通过例子讲解几种不同的方法,有JDK原生的方法,还有使用第 ...

  8. java 类 大全_JAVA集合类汇总

    缩略图如下图所示:图中,实线边框的是实现类,折线边框的是抽象类,而点线边框的是接口 在JAVA的util包中有两个所有集合的父接口Collection和Map,它们的父子关系: set --其中的值不 ...

  9. Java集合篇:集合类介绍

    上面的图展示了整个集合大家族的成员以及他们之间的关系.下面就上面的各个接口.基类做一些简单的介绍(主要介绍各个集合的特点,区别). 一.Collection接口: Collection接口是最基本的集 ...

最新文章

  1. 李飞飞点赞的NeurIPS新赛道,刚刚公布了第一批数据集benchmark入围名单
  2. 分享:手机应用存5个严重的信息安全隐患你晓得吗?
  3. abb外部轴零位校准_ABB机器人如何控制非同步联动外部轴
  4. 代码艺术~优雅的编程字体及对字体的感觉
  5. 每日程序C语言5-斐波那契兔子数
  6. ORACLE 12C采坑之 ORA-12541:TNS:无监听程序
  7. 如何在win10搜索计算机,如何在win10电脑的任务栏搜索框中添加地址?
  8. 使用c#调用XMLHTTP(XMLHTTPClass) ,发送和返回 json
  9. 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
  10. SharePoint:扩展DVWP - 第10部分:在表单操作工作流中传递工作流变量
  11. 开关稳压器工作原理与典型应用电路分析——LM2576、LM2596与LM2577
  12. java数据库加密(druid)
  13. 如何成为一名区块链工程师? | 附学习资源
  14. CentOS支持NTFS格式
  15. 拉文大学计算机科学,美国研究生语言双录取,这些大学有你中意的吗?
  16. 文本文件和二进制文件的区别和联系
  17. rimraf : 无法加载文件,‘set-executionpolicy‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  18. Nextcloud整合Aria2和AriaNg、Aria2 WebUI实现离线下载
  19. 《你可以不平凡》-- 周杰伦在北京大学百年讲堂的演讲
  20. ArcGIS字段计算器中的python函数(转发)

热门文章

  1. wifi搜索不到连接不上的问题(企业局域网wifi)
  2. 汇编语言——指令系统小结
  3. 儿童在未来游戏中的监管与保护趋势
  4. oracle utl inaddr,oracle11gr2中ACL对UTL_INADDR的授权报错,急急急
  5. Linux基础_软件包管理
  6. Docker快速入门与使用
  7. vue中v-charts图表数据如何从后台获取?【篇二】
  8. Winform运行后,界面尺寸与设计时不一样
  9. 【数据库】四(1)、数据查询之单表查询
  10. 多台路由器堆叠_网络技术篇(一)●如何将两台路由器设备进行堆叠