Java高级编程----集合

集合

  • 集合概述
    • Collection接口
    • List接口简介
    • ArrayList集合
    • Set接口简介
    • Hash Set接口简介
    • Map接口简介
    • TreeMap集合
    • Properties集合

集合概述

为了在程序中可以保存数目不确定的对象,Java提供了一系列特殊类,这些类可以存储任意类型的对象,并且长度可变。这些类统称为集合。
集合按照其存储结构可以分为两大类,单列集合Collection和双列集合Map,这两种集合的特点具体如下:

Collection接口

  • Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。其中,List的特点是元素有序、元素可重复,有索引。Set的特点是元素无序,而且不可重复,无索引。List接口的主要实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet和TreeSet。
    在这里插入图片描述
    Collection是所有单列集合的父接口,它定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。Collection接口的常用如下表。

List接口简介

在这里插入图片描述
List接口继承自Collection接口,是单列集合的一个重要分支。List集合允许出现重复的元素,所有的元素是以一种线性方式进行存储的,在程序中可以通过索引访问List集合中的指定元素。另外,List集合还有一个特点就是元素有序,即元素的存入顺序和取出顺序一致。
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引操作集合的特有方法。 List接口常用方法如下表。
在这里插入图片描述

ArrayList集合

ArrayList是List接口的一个实现类,它是程序中最常见的一种集合。在ArrayList内部封装了一个长度可变的数组对象,当存入的元素超过数组长度时,ArrayList会在内存中分配一个更大的数组来存储这些元素,因此可以将ArrayList集合看作一个长度可变的数组。
ArrayList集合中大部分方法都是从父类Collection和List继承过来的,其中add()方法和get()方法分别用于实现元素的存入和取出。接下来通过一个案例学习ArrayList集合的元素存取。

1 import java.util.*;
2 public class Example01 {
3    public static void main(String[] args) {
4    ArrayList list = new ArrayList(); // 创建ArrayList集5合
5        list.add("张三");                    // 向集合中添加元素
6        list.add("李四");
7        list.add("王五");
8        list.add("赵六");
9        // 获取集合中元素的个数
10        System.out.println("集合的长度:" + list.size()); 
11        // 取出并打印指定位置的元素
12        System.out.println("第2个元素是:" + list.get(1)); 
13    }
14 }

上述代码中,第4行代码创建了一个list对象,第5~8行代码使用list对象调用add(Object o)方法向ArrayList集合中添加了4个元素,第10行代码使用list对象调用size()方法获取集合中元素个数并输出打印,第12行代码使用list对象调用ArrayList的get(int index)方法取出指定索引位置的元素并输出打印。从运行结果可以看出,索引位置为1的元素是集合中的第二个元素,这就说明集合和数组一样,索引的取值范围是从0开始的,最后一个索引是size-1,在访问元素时一定要注意索引不可超出此范围,否则会抛出角标越界异常IndexOutOfBoundsException。
由于ArrayList集合的底层是使用一个数组来保存元素,在增加或删除指定位置的元素时,会导致创建新的数组,效率比较低,因此不适合做大量的增删操作。因为这种数组的结构允许程序通过索引的方式来访问元素,所以使用ArrayList集合查找元素很便捷。

Set接口简介

Set接口和List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。与List接口不同的是,Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储位置,具有良好的存取和查找性能。TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。

Hash Set接口简介

HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。接下来通过一个案例演示HashSet集合的用法。

1 import java.util.*;
2 public class Example07 {
3	public static void main(String[] args) {
4		HashSet set = new HashSet();   // 创建HashSet集合
5		set.add("张三");                  // 向该Set集合中添加字符串
6		set.add("李四");
7		set.add("王五");
8		set.add("李四");                  // 向该Set集合中添加重复元素
9		Iterator it = set.iterator(); // 获取Iterator对象
10		while (it.hasNext()) {          // 通过while循环,判断集合中是否有元素
11		 Object obj = it.next();// 如果有元素,就通过迭代器的next()方法获取元素
12			System.out.println(obj);
13		}
14	}
15 }

上述代码中,第4-8行代码是声明了一个HashSet集合并通过add()方法向HashSet集合依次添加了四个字符串;第9行代码是声明了一个迭代器对象it,第10~13行代码是通过Iterator迭代器遍历所有的元素并输出。从打印结果可以看出,取出元素的顺序与添加元素的顺序并不一致,并且重复存入的字符串对象“李四”被去除了,只添加了一次。
HashSet集合之所以能确保不出现重复的元素,是因为它在存入元素时做了很多工作。当调用HashSet集合的add()方法存入元素时,首先调用当前存入对象的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,就将该元素舍弃。
在这里插入图片描述

1 import java.util.*;
2 class Student {
3	String id;
4	String name;		    		 
5	public Student(String id,String name) {	  // 创建构造方法
6		this.id=id;
7		this.name = name;
8	}
9	public String toString() {		// 重写toString()方法
10		return id+":"+name;
11	}
12 }
13 public class Example08 {
14	public static void main(String[] args) {
15		HashSet hs = new HashSet();	// 创建HashSet集合
16		Student stu1 = new Student("1", "张三");    // 创建Student对象
17		Student stu2 = new Student("2", "李四");
18		Student stu3 = new Student("2", "李四");
19		hs.add(stu1);
20		hs.add(stu2);
21		hs.add(stu3);
22		System.out.println(hs);
23	}
24 }

在这里插入图片描述
上述代码中,第15行代码声明了一个HashSet集合,第16-18行代码分别声明了3个Student对象,第19~22行代码是分别将3个Student对象存入HashSet集合中并输出。图6-18所示的运行结果中出现了两个相同的学生信息“2:李四”,这样的学生信息应该被视为重复元素,不允许同时出现在HashSet集合中。之所以没有去掉这样的重复元素,是因为在定义Student类时没有重写hashCode()和equals()方法。
HashSet集合存储的元素是无序的,如果想让元素的存取顺序一致,可以使用Java中提供的LinkedHashSet类,LinkedHashSet类是HashSet的子类,与LinkedList一样,它也使用双向链表来维护内部元素的关系。

Map接口简介

Map接口是一种双列集合,它的每个元素都包含一个键对象Key和值对象Value,键和值对象之间存在一种对应关系,称为映射。从Map集合中访问元素时,只要指定了Key,就能找到对应的Value。
在这里插入图片描述
HashMap集合是Map接口的一个实现类,用于存储键值映射关系,但HashMap集合没有重复的键并且键值无序

1 import java.util.*;
2 public class Example14 {
3	public static void main(String[] args) {
4		HashMap map = new HashMap(); // 创建Map对象
5		map.put("1", "张三");     // 存储键和值
6		map.put("2", "李四");
7		map.put("3", "王五");
8		System.out.println("1:" + map.get("1"));  // 根据键获取值
9		System.out.println("2:" + map.get("2"));
10		System.out.println("3:" + map.get("3"));
11	}
12 }

上述代码中,第4-7行代码声明了一个HashMap集合并通过Map的put(Object key,Object value)方法向集合中加入3个元素,第8~10行代码是通过Map的get(Object key)方法获取与键对应的值。

Map集合中的键具有唯一性,现在向Map集合中存储一个相同的键看看会出现什么情况,在第7行代码下面增加一行代码,如下所示:
map.put(“3”, “赵六”);
修改之后,再次运行程序,运行结果如下图。在这里插入图片描述
Map中仍然只有3个元素,只是第二次添加的值“赵六”覆盖了原来的值“王五”,这也证实了Map中的键必须是唯一的,不能重复,如果存储了相同的键,后存储的值则会覆盖原有的值,简而言之就是:键相同,值覆盖。
在程序开发中,经常需要取出Map中所有的键和值,那么如何遍历Map中所有的键值对呢?有两种方式可以实现,第一种方式就是先遍历Map集合中所有的键,再根据键获取相应的值。

接下来通过一个案例来演示先遍历Map集合中所有的键,再根据键获取相应的值。

1 import java.util.*;
2 public class Example15 {
3	public static void main(String[] args) {
4		HashMap map = new HashMap();  // 创建Map集合
5		map.put("1", "张三");               // 存储键和值
6		map.put("2", "李四");
7		map.put("3", "王五");
8		Set keySet = map.keySet();         // 获取键的集合
9		Iterator it = keySet.iterator();  // 迭代键的集合
10		while (it.hasNext()) {
11			Object key = it.next();
12			Object value = map.get(key);  // 获取每个键所对应的值
13			System.out.println(key + ":" + value);
14		}
15	}
16 }

上述代码中,第8~14行代码是第一种遍历Map的方式。首先调用Map对象的KeySet()方法,获得存储Map中所有键的Set集合,然后通过Iterator迭代Set集合的每一个元素,即每一个键,最后通过调用get(String key)方法,根据键获取对应的值。

Map中,还提供了一些操作集合的常用方法,例如,values()方法用于得到map实例中所有的value,返回值类型为Collection;size()方法获取map集合类的大小;containsKey()方法用于判断是否包含传入的键;containsValue()方法用于判断是否包含传入的值;remove()方法用于根据key移除map中的与该key对应的value等。

TreeMap集合

HashMap集合存储的元素的键值是无序的和不可重复的,为了对集合中的元素的键值进行排序,Map接口提供了另一个可以对集合中元素键值进行排序的类TreeMap。

1 import java.util.Iterator;
2 import java.util.Set;
3 import java.util.TreeMap;
4 public class Example19 {
5    public static void main(String[] args) {
6        TreeMap map = new TreeMap();      // 创建Map集合
7        map.put(3, "李四");// 存储键和值
8        map.put(2, "王五");
9        map.put(4, "赵六");
10        map.put(3, "张三"); 
11 Set keySet = map.keySet();
12        Iterator it = keySet.iterator();
13        while (it.hasNext()) {
14            Object key = it.next();
15            Object value = map.get(key); // 获取每个键所对应的值
16            System.out.println(key+":"+value);
17        }
18    }
19 }

上述代码中,第6-10行代码是通过Map的put(Object key,Object value)方法向集合中加入4个元素;第11~17行代码是使用迭代器遍历集合中的元素并通过元素的键获取对应的值,并打印。从运行结果可以看出,添加的元素已经自动排序,并且键值重复存入的整数3只有一个,只是后边添加的值“张三”覆盖了原来的值“李四”。这也证实了TreeMap中的键必须是唯一的,不能重复并且有序,如果存储了相同的键,后存储的值则会覆盖原有的值。

TreeMap集合之所以可以对添加的元素的键值进行排序,其实现同TreeSet一样,TreeMap的排序也分自然排序与比较排序两种。接下来通过一个案例演示比较排序法实现按键值排序,在该案例中,键是自定义类值是String类。

1 import java.util.*;
2 class Student {
3    private String name;
4    private int age;
5    public String getName() {
6        return name;
7    }
8    public void setName(String name) {
9        this.name = name;
10    }
11 public int getAge() {
12        return age;
13    }
14    public void setAge(int age) {
15        this.age = age;
16    }
17    public Student(String name, int age) {
18        super();
19        this.name = name;
20        this.age = age;
21    }
22 @Override
23    public String toString() {
24        return "Student [name=" + name + ", age=" + age + "]";
25    }
26 }
27 public class Example20 {
28    public static void main(String[] args) {
29        TreeMap tm = new TreeMap(new Comparator<Student>() {
30            @Override
31            public int compare(Student s1, Student s2) {
32                int num = s1.getName().compareTo(s2.getName());//按照姓名比较
33                return num == 0 ? num:s1.getAge() - s2.getAge();
34            }
35        });
36 tm.put(new Student("张三", 23), "北京");
37        tm.put(new Student("李四", 13), "上海");
38        tm.put(new Student("赵六", 43), "深圳");
39        tm.put(new Student("王五", 33), "广州");
40        Set keySet = tm.keySet();
41        Iterator it = keySet.iterator();
42        while (it.hasNext()) {
43            Object key = it.next();
44            Object value = tm.get(key); // 获取每个键所对应的值
45            System.out.println(key+":"+value);
46        }
47    }
48 }

上述代码中,第2-26行代码定义了一个Student类;第29-35行代码定义了一个TreeMap集合,并在该集合中通过匿名内部类的方式实现了Comparator接口,然后重写了compare()方法,在compare()方法中通过三目运算符的方式自定义了排序方式为先按照年龄排序,年龄相同再按照姓名排序。第36~46行代码是通过Map的put(Object key,Object value)方法向集合中加入4个键为Student对象值为String类型的元素,并使用迭代器将集合中元素打印输出。

Properties集合

Map接口中还有一个实现类Hashtable,它和HashMap十分相似,区别在于Hashtable是线程安全的。Hashtable存取元素时速度很慢,目前基本上被HashMap类所取代,但Hashtable类有一个子类Properties在实际应用中非常重要。
Properties主要用来存储字符串类型的键和值,在实际开发中,经常使用Properties集合来存取应用的配置项。假设有一个文本编辑工具,要求默认背景色是红色,字体大小为14px,语言为中文,其配置项如下面的代码:

Backgroup-color = red
Font-size = 14px
Language = chinese

在程序中可以使用Properties集合对这些配置项进行存取,接下来通过一个案例学习Properties集合的使用。

1 import java.util.*;
2 public class Example21 {
3   public static void main(String[] args) {
4	   Properties p=new Properties();             // 创建Properties对象
5	   p.setProperty("Backgroup-color", "red");
6	   p.setProperty("Font-size", "14px");
7	   p.setProperty("Language", "chinese");
8	   Enumeration names = p.propertyNames();//获取Enumeration对象所有键枚举
9	   while(names.hasMoreElements()){           // 循环遍历所有的键
10	    	  String key=(String) names.nextElement();
11	       String value=p.getProperty(key);        // 获取对应键的值
12	    	  System.out.println(key+" = "+value);
13	    }
14	}
15 }

上述代码的Properties类中,针对字符串的存取提供了两个专用的方法setProperty()和getProperty()。setProperty()方法用于将配置项的键和值添加到Properties集合当中。在第8行代码中通过调用Properties的propertyNames()方法得到一个包含所有键的Enumeration对象,然后在遍历所有的键时,通过调用getProperty()方法获得键所对应的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/167349.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Espressif-IDE中使用Wokwi仿真ESP32

陈拓 2023/10/17-2023/10/19 1. 概述 在Espressif-IDE v2.9.0版本之后可直接在IDE中使用Wokwi模拟器。 1.1 什么是 Wokwi 模拟器&#xff1f; Wokwi 是一款在线电子模拟器&#xff0c;支持模拟各种开发板、元器件和传感器&#xff0c;例如乐鑫产品 ESP32。 Wokwi 提供基于浏…

推理引擎之模型压缩浅析

目录 前言1. 模型压缩架构和流程介绍2. 低比特量化原理2.1 量化基础介绍2.2 量化方法2.3 量化算法原理2.4 讨论 3. 感知量化训练QAT原理3.1 QAT原理3.2 量化算子插入3.3 QAT训练流程3.4 QAT衍生研究3.5 讨论 4. 训练后量化PTQ4.1 动态PTQ4.2 静态PTQ4.3 KL散度实现静态PTQ4.4 量…

SystemVerilog Assertions应用指南 Chapter 1.14蕴含操作符

1.14蕴含操作符 属性p7有下列特别之处 (1)属性在每一个时钟上升沿寻找序列的有效开始。在这种情况下,它在每个时钟上升沿检查信号“a”是否为高。 (2)如果信号“a”在给定的任何时钟上升沿不为高,检验器将产生一个错误信息。这并不是一个有效的错误信息,因为我…

Leetcode 454 四数相加II(哈希表 + getOrDefault方法用于获取Map中指定键的值,如果键不存在,则返回一个默认值)

Leetcode 454 四数相加II&#xff08;哈希表&#xff09; 解法1 HashMap getOrDefault方法 解法1 HashMap getOrDefault方法 【HashMap】 【⭐️HashMap常用操作】 创建HashMap&#xff1a;HashMap<Integer, Integer> hash new HashMap<>(); 向HashMap添加元素…

【类和对象+this引用】

文章目录 面向对象与面向过程面向对象关注的是对象&#xff0c;用类描述这个对象如何定义类如何更改类名 类的实例化this引用总结 面向对象与面向过程 面向对象就是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。 面向过程好比传统的洗衣服方式&#x…

17 Transformer 的解码器(Decoders)——我要生成一个又一个单词

Transformer 编码器 编码器在干吗&#xff1a;词向量、图片向量&#xff0c;总而言之&#xff0c;编码器就是让计算机能够更合理地&#xff08;不确定性的&#xff09;认识人类世界客观存在的一些东西 Transformer 解码器 解码器会接收编码器生成的词向量&#xff0c;然后通…

STM32,我想看单片机上的外设时钟,我怎么看?

一&#xff1a;在工程中加入rcc文件 首先需要加载我们的时钟函数的文件 stm32f10x_rcc.h 和 stm32f10x_rcc.c 文件 二&#xff1a;查看文件 在h头文件 尾部&#xff0c;有我们这个总线的函数 在函数体内&#xff0c;有我们这个宏定义的 外设时钟&#xff0c;我们拿就行了 APB2_…

App分发的策略和注意事项

当今的数字化时代中&#xff0c;移动应用程序已经成为了人们生活中不可或缺的一部分。随着智能手机的普及和移动互联网的快速发展&#xff0c;应用程序的分发方式也变得越来越多样化。 App分发是指将移动应用程序通过特定的渠道传递给终端用户的过程。在应用程序开发完成后&am…

解决matlab报错“输入参数的数目不足”

报错语句&#xff1a;tanh((peakNums-parameter)/2) 报错提示&#xff1a;输入参数的数目不足 运行环境&#xff1a;matlab2021b 分析原因&#xff1a; 当执行peakNums - parameter时&#xff0c;如果peakNums和parameter都是向量&#xff0c;那么这并不一定意味着会得到对应…

2.卷积神经网络(CNN)

一句话引入&#xff1a; 如果我们要做图像识别&#xff0c;用的是一个200x200的图片&#xff0c;那么BP神经网络的输入层就需要40000个神经元&#xff0c;因为是全连接&#xff0c;所以整个BP神经网络的参数量就是160亿个&#xff0c;显然不能这样来训练网络&#xff0c;所以我…

HBuilder插件推荐

整理一下我觉得好用的插件&#xff0c;后期可能会有更改 eslint-js eslint-plugin-vue Prettier scss/sass编译 右键复制vue页面路径&#xff0c;主要用于快速复制vue页面的路径到浏览器

订单30分钟自动关闭的五种解决方案

1 前言 在开发中&#xff0c;往往会遇到一些关于延时任务的需求。例如 生成订单30分钟未支付&#xff0c;则自动取消生成订单60秒后,给用户发短信 对上述的任务&#xff0c;我们给一个专业的名字来形容&#xff0c;那就是延时任务 。那么这里就会产生一个问题&#xff0c;这…

基于Java的汽车维修预约管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

Java学习_day03_变量数据类型运算符

文章目录 变量定义声明赋值使用简化 数据类型基本数据类型整型浮点型布尔型字符型空型 引用数据类型数据类型转换自动类型转换强制类型转换 运算符算术运算符赋值运算符比较运算符逻辑运算符位运算符条件运算符一元运算符二元运算符三元运算符运算符优先级 变量 变量类似于数学…

云服务器搭建Hadoop分布式

文章目录 1.服务器配置2.Java环境3. 安装Hadoop4. 集群配置5. 编写集群的启动脚本 1.服务器配置 服务器主机名配置115.157.197.82s110核115.157.197.84s210核115.157.197.109s310核115.157.197.31s410核115.157.197.60gracal10核 所有的软件安装在/opt/module下&#xff0c;软…

光学知识整理-偏振光

偏振光 目录基础概念基础概念的补充平面偏振光&#xff08;线偏振光&#xff09;部分偏振光圆偏振光椭圆偏振光菲涅耳公式相位关系 反射折射所引起的偏振态的改变斯托克斯倒逆关系重要参数 目录 基础概念 光是横波&#xff1a;光是电磁波,其电场分量(电场强度)E、磁场分量(磁…

biquad滤波器的设计

1.介绍 Biquad滤波器是一种常用的数字滤波器结构&#xff0c;它使用二阶差分方程&#xff08;difference equation&#xff09;来实现滤波功能。它得名于其包含两个极点&#xff08;poles&#xff09;和一个零点&#xff08;zero&#xff09;。 双二阶滤波器(biquad)是最常用…

当我让文心一言写个代码来庆祝1024程序员节,它写的代码是……

先让它写个自我介绍吧~ 大家好&#xff0c;我是一个人工智能语言模型&#xff0c;我的中文名是文心一言&#xff0c;英文名是ERNIE Bot。我可以协助您完成范围广泛的任务并提供有关各种主题的信息&#xff0c;比如回答问题&#xff0c;提供定义和解释及建议。如果您有任何问题…

改进YOLOv5 | 头部解耦 | 将YOLOX解耦头添加到YOLOv5 | 涨点杀器

改进YOLOv5 | 头部解耦 | 将YOLOX解耦头添加到YOLOv5 论文地址:https://arxiv.org/abs/2107.08430 文章目录 改进YOLOv5 | 头部解耦 | 将YOLOX解耦头添加到YOLOv51. 解耦头原理2. 解耦头对收敛速度的影响3. 解耦头对精度的影响4. 代码改进方式第一步第二步第三步第四步第五步本…