Java高级编程----集合

news2024/11/18 3:21:54

集合

  • 集合概述
    • 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.coloradmin.cn/o/1121101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用java mail SMTPTransport发送邮箱,本地秒到,一上服务器就20-30s左右,生产环境直接发送失败。

一、代码 pom文件 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><!--pom.xml添加javax.mail的引用&#xff0c;或者项目引入…

【最短路径算法】一文掌握Dijkstra算法,详解与应用示例+代码

目录 1 Dijkstra算法 2 Dijkstra算法的步骤 3 Dijkstra算法python实现 4 Dijkstra算法应用示例详解 1 Dijkstra算法 Dijkstra算法&#xff08;迪杰斯特拉算法&#xff09;是一种用于在加权图中查找从一个起始节点到所有其他节点的最短路径的算法。该算法最初由荷兰计算机科…

JVM 基础篇:类加载器

一.了解JVM 1.1什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟计算机功能来实现的&#xff0c;JVM屏蔽了与具体操作系统平台相关的信息&#xff0c;Java程序只需…

通讯录和内存动态管理

目录 (通讯录)动态增长版 实现效果 找单身狗 题目 源码 思路 三个内存函数的模拟实现 模拟实现strncpy 模拟实现strncat 模拟实现atoi (通讯录)动态增长版 该版本通讯录在原版的基础上增加了检查容量函数&#xff0c;实现了通讯录的动态…

在PS中轻松实现肖像磨皮,感受Imagenomic Portraiture 4的强大

每个人都希望自己的肖像照片看起来漂亮、清晰并且光滑。然而&#xff0c;在处理肖像照片时&#xff0c;要达到这些效果通常需要花费大量时间和精力。如果您正在寻找一种简单快捷的方法来优化您的肖像照片&#xff0c;那么Imagenomic Portraiture 4插件将是您的理想选择。 Imag…

单接口的批量测试如何实现

一、痛点&#xff1a;一条测试数据对应一个测试方法 前面的章节中我们已经写代码实现了登录接口的处理调用&#xff0c;但是一个接口往往是需要多条测试用例才能完整的覆盖到每一种情况&#xff0c;针对于单接口多条测试用例需要执行的情况&#xff0c;该如何处理呢&#xff0…

uboot移植之mx6ull_alientek_nand.h文件详解一

一. 简介 mx6ull_alientek_nand.h文件是 开发板的 uboot的一个配置文件。每个开发板都有一个 .h的配置文件。 mx6ull_alientek_nand.h文件其实是 之前针对正点原子ALPHA开发板移植的 Uboot配置文件。 本文简单分析一下 针对正点原子ALPHA开发板的 配置文件&#xff1a; mx6u…

STL模拟实现—vector

引言&#xff1a;本篇文章主要是模拟实现vector&#xff0c;但不同于stl中vector的成员变量都是迭代器&#xff0c;这个自定义的vector是一个T* 的数据变量和一个int类型的size和int类型的capacity。&#xff08;有时间再写三个迭代器的版本吧&#xff01;&#xff09; 首先来看…

Redis学习(第八章缓存策略)

目录 RdisExample 课程介绍 1.Redis介绍 2.Redis 安装 3. Redis的数据结构 4. Redis缓存特性 5. Redis使用场景 6. Redis客户端-Jedis 7. Jedis Pipeline 8. Redis缓存策略 学习资料 QA 相关问题 http, socket ,tcp的区别 RdisExample 项目代码地址&#xff1a;htt…

Leetcode—104.二叉树的最大深度【简单】

2023每日刷题&#xff08;六&#xff09; Leetcode—104.二叉树的最大深度 递归实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/int maxDepth(struct TreeNode* root){…

2017年高热度编程语言简介

世上语言千千万&#xff0c;我却独爱这一种!”这句话用来形容程序员和编程语言之间的爱恨情仇实在是再精准不过了。根据GitHub 2016年的开源报告&#xff0c;其上所有开源项目共包含了316种编程语言&#xff0c;这是一个什么概念呢?举个例子来说&#xff0c;世界上共有226个国…

高防CDN的发展趋势

随着互联网的迅速发展&#xff0c;网站和在线服务的安全性变得至关重要。网络攻击如DDoS攻击和恶意流量正在增加&#xff0c;因此高防CDN&#xff08;高防御内容分发网络&#xff09;成为网络安全的重要组成部分。本文将探讨高防CDN未来的发展趋势&#xff0c;并比较其与传统CD…

PyCharm改变代码背景图片的使用教程

一个好的集成环境是学习和使用一门编程语言的重中之重&#xff0c;这次我给大家分享如何改变PyCharm软件的代码背景图片。 说明&#xff1a;本教程使用的是汉化版PyCharm软件。 打开PyCharm软件。 点击软件最上方导航栏的文件&#xff0c;然后找到设置。 打开设置然后点击外观…

小米妙享无法正常启动,用非管理员权限启动

网上找到的其他方法大多数不太好 1.非管理员方式运行的方法 1.创建一个用户123&#xff0c;密码123 2.创建一个bat文件&#xff0c;复制粘贴以下内容 runas /savecred /user:123 “C:\Program Files\MI\AIoT\Launch.exe” 第一次点击运行&#xff0c;要输入密码&#xff0c;以…

面试官:说说webpack的热更新是如何做到的?

一、是什么 HMR 全称 Hot Module Replacement&#xff0c;可以理解为模块热替换&#xff0c;指在应用程序运行过程中&#xff0c;替换、添加、删除模块&#xff0c;而无需重新刷新整个应用 例如&#xff0c;我们在应用运行过程中修改了某个模块&#xff0c;通过自动刷新会导致…

靶机 DC_1

DC_1 信息搜集 存活检测 详细扫描 网页目录扫描 网页信息搜集 cms 为 Drupal 漏洞利用 使用 msf 搜索 drupal 的漏洞 启动 msfconsole搜索 search drupal尝试编号为 0 的漏洞 失败 利用编号为 1 的漏洞 use 1查看需要配置的选项 show options设置目标 ip set rhost 10…

Leetcode—1726.同积元组【中等】

2023每日刷题&#xff08;六&#xff09; Leetcode—1726.同积元组 哈希表解题思路 实现代码 class Solution { public:int tupleSameProduct(vector<int>& nums) {unordered_map<int, int>count;int n nums.size();int i, j;for(i 0; i < n - 1; i) {f…

C语言实现单链表(图解增删查改+代码)

文章目录 写在前面1. 链表节点的定义2. 链表的创建3. 插入数据3.1 头插3.2 尾插3.3 在指定位置的前面插入数据 4. 删除数据4.1 头删4.2 尾删4.3 删除指定位置的数据 5. 查找数据5. 链表的销毁 写在前面 上面文章用C语言实现了顺序表的增删查改&#xff0c;本片文章继续用C语言…

web各个指标理解

QPS : 单位时间得请求次数 TPS &#xff1a;单位时间得事务数 并发 &#xff1a; QPS *单位响应时间 pv &#xff1a;进入一个网站&#xff0c;又单击打开该网站的其他页面&#xff0c;每打开一个页面就 增加一个PV,甚至在同一页面每刷新一次也多一个PV 二八定律&#xff1a;百…

nonaDlA 逻辑分析仪 使用记录

注意事项&#xff0c;很灵敏&#xff0c;不要用手碰&#xff0c;产生误触发 安装软件 github地址 官方提供的淘宝地址与使用说明 1.安装 1.安装程序 &#xff1a;下载githubDLA源码&#xff0c;打开 software\PulseView.exe安装 2.安装驱动&#xff1a;安装完第一步后&a…