集合框架(2)List
Collection的子接口:List、Set
1、List接口
- 鉴于Java中数组用来存储数据的局限性,我们通常使用java.util.List替代数组
- List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
- JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。
(1) List接口方法
List除了从Collection集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法。
- 插入元素
- void add(int index, Object ele):在index位置插入ele元素,其余元素自动后移一位,若容量不够则自动扩容
- boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
- 获取元素
- Object get(int index):获取指定index位置的元素
- List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
- 获取元素索引
- int indexOf(Object obj):返回obj在集合中首次出现的位置
- int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
- 删除和替换元素
- Object remove(int index):移除指定index位置的元素,并返回此元素
- Object remove(Object obj) : 移除与obj相同的元素
- Object set(int index, Object ele):设置指定index位置的元素为ele
@Test
public void test(){List list = new ArrayList();list.add("faculty");//全体教员list.add("poll");//民意调查list.add("render");//给予list.add("descend");//下降list.add(2);list.add(new Person("Qum",18));//add(int index,Collection eles)List<Integer> list1 = Arrays.asList(1, 2, 3);list.addAll(3,list1);System.out.println(list);list.remove(2);//移除索引2System.out.println(list);list.remove(Integer.valueOf(2));//若有重复的2,只删除一个System.out.println(list);}
2、List接口主要实现类:
(1)主要实现类:ArrayList
java.util.Collection:存储一个一个的数据
--子接口:List 存储有序的、可重复的数据(“动态”数组)
--ArrayList:
ArrayList是线程不安全的,效率更高。
Vecor线程安全,效率低,版本古老,一般不使用。
- ArrayList 是 List 接口的主要实现类
- 本质上,ArrayList是对象引用的一个”变长”数组(如果长度不够,可以自动扩容)Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合
List list = new ArrayList();//体现多态性,创建一个ArrayList的对象,将其赋值给List型的引用变量。
//初始化创建list集合时,底层创建空数组
list.add("illusion");//第一次添加元素时,默认将底层集合容量设置为10.若之后容量不够,可自动扩容
list.add("realm");
list.add("verify");
list.add("accumulate");String []strings = new String[]{"radical","convention","outline","cling","neutral"};
list.addAll(Arrays.asList(strings));//将数组strings中的元素全都转化为集合的元素
- 底层使用Object[]存储,添加、查找数据时效率较高;插入、删除数据时效率较低;
(2)实现类之二:LinkedList
- 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。这是由底层采用链表(双向链表)结构存储数据决定的。
- 但是添加、查找数据时效率较低。
- 特有方法:
- void addFirst(Object obj)
- void addLast(Object obj)
- Object getFirst()
- Object getLast()
- Object removeFirst()
- Object removeLast()
(3)List的实现类之三:Vector
- Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
- 在各种List中,最好把ArrayList作为默认选择。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。
- 特有方法:
- void addElement(Object obj)
- void insertElementAt(Object obj,int index)
- void setElementAt(Object obj,int index)
- void removeElement(Object obj)
- void removeAllElements()
3、Set接口概述
- Set接口是Collection的子接口,Set接口相较于Collection接口没有提供额外的方法
- Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
- Set集合支持的遍历方式和Collection集合一样:foreach和Iterator。
- Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。
Set主要实现类:HashSet
java.util.Colection:存储一个一个的数值
--子接口:Set接口:存储无序的、不可重复的数据(集合)
--HashSet:主要实现类,底层使用HashMap,使用数组+单向链表+红黑树的结构进行存储(在JDK8中)
-LinkedHashSet:HashSet的子类,在现有的数组+单向链表+红黑树的结构的基础上,又添加了一组双向链表,用于记录添加元素的先后顺序,可以按照添加元素的先后顺序进行遍历。
--TreeSet,底层使用红黑树存储,可以按照添加元素的指定属性的大小顺序进行遍历。-
set的无序性:<1> 无序性不等于随机性。
无序性:不像ArrayList一样依次紧密排列,而是根据添加元素的Hash值不同,计算其在数组中的存储位置进行排列,因为此位置不是依次排列的,所以表现出无序性。
set的不可重复性:添加到set中的元素不能相同。比较的标准,需要判断hashCode()得到的哈希值和equals方法得到的布尔值。
只有哈希值和布尔值都相同,才认为两个元素相同,不允许放入集合。
(1)HashSet概述
- HashSet 是 Set 接口的主要实现类,大多数时候使用 Set 集合时都使用这个实现类。
- HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存储、查找、删除性能。
- HashSet 具有以下特点:
- 不能保证元素的排列顺序
- HashSet 不是线程安全的
- 集合元素可以是 null
- HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法得到的哈希值相等,并且两个对象的 equals()方法返回值为true。
- 对于存放在Set容器中的对象,对应的类一定要重写hashCode()和equals(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
- HashSet集合中元素的无序性,不等同于随机性。这里的无序性与元素的添加位置有关。具体来说:我们在添加每一个元素到数组中时,具体的存储位置是由元素的hashCode()调用后返回的hash值决定的。导致在数组中每个元素不是依次紧密存放的,表现出一定的无序性。
(2)HashSet中添加元素的过程:
- 第1步:当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法得到该对象的 hashCode值,然后根据 hashCode值,通过某个散列函数决定该对象在 HashSet 底层数组中的存储位置。
- 第2步:如果要在数组中存储的位置上没有元素,则直接添加成功。
- 第3步:如果要在数组中存储的位置上有元素,则继续比较:
- 如果两个元素的hashCode值不相等,则添加成功;
- 如果两个元素的hashCode()值相等,则会继续调用equals()方法:
- 如果equals()方法结果为false,则添加成功。
- 如果equals()方法结果为true,则添加失败。
- 2步添加成功,元素会保存在底层数组中。
- 3步两种添加成功的操作,由于该底层数组的位置已经有元素了,则会通过链表的方式继续链接,存储。
HashCode与LickedHashSet中元素的要求:
重写equals方法和hashCode方法,且保持一致性
@Test
public void test1(){Set set = new HashSet();set.add("AAA");set.add("descend");set.add(123);set.add(123);//不输出Integer integer = Integer.valueOf("123");set.add(integer);Iterator iterator = set.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}
重写 hashCode() 方法的基本原则
- 在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。
- 当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。
- 对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
注意:如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
5.2.4 重写equals()方法的基本原则
- 重写equals方法的时候一般都需要同时复写hashCode方法。通常参与计算hashCode的对象的属性也应该参与到equals()中进行计算。
- 推荐:开发中直接调用Eclipse/IDEA里的快捷键自动重写equals()和hashCode()方法即可。
- 为什么用Eclipse/IDEA复写hashCode方法,有31这个数字?
- hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)
其次,31只占用5bits,相乘造成数据溢出的概率较小。
再次,31可以 由i*31== (i<<5)-1来表示,现在很多虚拟机里面都有做相关优化。(提高算法效率)
最后,31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终出来的结果只能被素数本身和被乘数还有1来整除!(减少冲突)
Set实现类之二:LinkedHashSet
- LinkedHashSet 是 HashSet 的子类,不允许集合元素重复。
- LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以添加顺序保存的。
- LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
5.4 Set实现类之三:TreeSet
5.4.1 TreeSet概述
- TreeSet 是 SortedSet 接口的实现类,TreeSet 可以按照添加的元素的指定的属性的大小顺序进行遍历。
- TreeSet底层使用红黑树结构存储数据
- 新增的方法如下: (了解)
- Comparator comparator()
- Object first()
- Object last()
- Object lower(Object e)
- Object higher(Object e)
- SortedSet subSet(fromElement, toElement)
- SortedSet headSet(toElement)
- SortedSet tailSet(fromElement)
- TreeSet特点:不允许重复、实现排序(自然排序或定制排序)
- TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
- 自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。
- 如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
- 实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
- 自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。
@Test
public void test1(){TreeSet treeSet = new TreeSet();treeSet.add("affluent");treeSet.add("constrain");treeSet.add("revelation");treeSet.add("interval");//treeSet.add(123);ClassCastException异常,TreeSet类中应当add加入同一类型的元素Iterator iterator = treeSet.iterator();while (iterator.hasNext()){System.out.println( iterator.next());//输出时按照默认排序输出}
-
- 定制排序:如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。
- 利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
- 要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。
- 定制排序:如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。
- 因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象。
- 对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 或compare(Object o1,Object o2)方法比较返回值。返回值为0,则认为两个对象相等。
- TreeSet集合不再考虑HashCode和equals方法,是否重写不再重要。
public class User implements Comparable{private String name;private int age;public User() {}public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {System.out.println("equals...");if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return age == user.age && Objects.equals(name, user.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic int compareTo(Object o) {if (this == o){return 0;}if (o instanceof User){User user = (User) o;return this.age- user.age;}throw new RuntimeException();}
}@Test
public void test3(){Comparator comparator = new Comparator() {@Overridepublic int compare(Object o1, Object o2) {if (o1 instanceof User && o2 instanceof User){User u1 = (User) o1;User u2 = (User) o2;int value = u1.getName().compareTo(u2.getName());if (value!=0){return value;}return u1.getAge()-u2.getAge();}throw new RuntimeException();}};//实现匿名内部类,创建实例对象comparatorTreeSet treeSet = new TreeSet(comparator);//按照定制排序的顺序进行排序User u1 = new User("Tom",13);User u2 = new User("Flank",24);User u3 = new User("Ry",999);User u4 = new User("Serial",999);treeSet.add(u1);treeSet.add(u2);treeSet.add(u3);treeSet.add(u4);Iterator iterator = treeSet.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}
}
相关文章:
集合框架(2)List
Collection的子接口:List、Set 1、List接口 鉴于Java中数组用来存储数据的局限性,我们通常使用java.util.List替代数组List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。JDK API中List接口的实现类常用的有ÿ…...
【子查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
西安理工大学丨ChatGPT助力学术论文写作训练营-助力发表SCI一区、二区
在当今学术研究中,科研人员在撰写论文时面临诸多挑战。首先是信息量的剧增,科研人员需要快速消化新知识,筛选相关信息并清晰表达。但论文写作不仅是信息的罗列,还需要条理清晰、逻辑严密、语言精准,特别是在竞争激烈的…...
go get依赖包失败,502 Bad gateway
问题描述 go get 依赖包失败,502 Bad gateway 解决办法 # 临时 export GOPROXY"https://goproxy.cn" go get -u xxxx # 或者直接永久生效 go env -w GOPROXY"https://goproxy.cn"...
71、docker镜像制作上传/下载到阿里云
基本思想:简单学习一下如何制作镜像和上传下载到私有阿里云,然后构建一个gpu的训练/推理环境,以备后续使用 一、配置环境 ubuntu@ubuntu:~$ sudo apt-get install docker.ioubuntu@ubuntu:~$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS P…...
ZLMediaKit+wvp (ffmpeg+obs)推拉流测试
这里使用了两种方式: ffmpeg命令和 OBS OBS推流在网上找了些基本没有说明白的, 在ZLMediaKit的issues中看到了一个好大哥的提问在此记录一下 使用OBS推流,rtmp,报鉴权失败 推流 1. ffmpeg命令推流 官方说明文档地址: 推流规则 rtsp://192.168.1.4:10554…...
POSTGRESQL跟ORACLE语法区别和相同之处
跟ORACLE语法区别之处 1. Update和delete语法区别 Pg 和MySQL Update和delete的时候表名不能加别名 2. 插入数字类型不一样 ORACLE 对number类型的数据可以用’’ 字符串标记插入,但是PG不行,必须要进行正确的数据类型 3. SEQ使用不同 ORACEL的SEQ…...
【知识点】图与图论入门
何为图论 见名知意,图论 (Graph Theory) 就是研究 图 (Graph) 的数学理论和方法。图是一种抽象的数据结构,由 节点 (Node) 和 连接这些节点的 边 (Edge) 组成。图论在计算机科学、网络分析、物流、社会网络分析等领域有广泛的应用。 如下,这…...
FPGA系列,文章目录
前言 FPGA(Field-Programmable Gate Array,现场可编程门阵列)是一种集成电路,其内部结构可以通过软件重新配置来实现不同的逻辑功能。与传统的ASIC(Application-Specific Integrated Circuit,专用集成电路…...
PAT乙级1003我要通过的做题笔记
分析题意 得到“答案正确”的条件是: 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字母 A 组成的字符串࿱…...
【React】React常用开发工具
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、React DevTools二、Redux DevTools三、Create React App 前言 React 是一种用于构建用户界面的流行 JavaScript 库,由于其灵活性、性能和可重用…...
Ubuntu20.04编译安装Carla全过程
前言 Carla的安装是我现阶段解决的第一个问题,现记录一下我安装Carla的过程以及我在安装过程中遇到的一些问题。 一、安装前准备 1、硬件环境 carla是一款基于UE4开发的模拟仿真软件,本身对硬件的要求比较高。 我是windows与ubuntu双系统࿰…...
Dijkstra 算法 是什么?
Dijkstra 算法 Dijkstra 算法是一种经典的最短路径算法,用于在图(有向或无向图)中找到从起点到其他所有节点的最短路径。它以广度优先搜索的方式,逐步扩展到目标节点,确保计算出的路径是最短的。 1. Dijkstra 算法的基…...
英文输入法---华为OD机试2024年E卷
题解: 代码:...
理解 package.json 中版本号符号
今天,聊一聊在前端开发中, package.json 中怎么看版本号符号。 版本号符号的解释 版本号通常由三部分组成:主版本号、次版本号、补丁版本号,格式为 major.minor.patch。常见的符号有: ^:更新时允许自动…...
计算机网络-IPSec VPN基本概念
企业分支之间经常有互联的需求,企业互联的方式很多,可以使用专线线路或者Internet线路。部分企业从成本和需求出发会选择使用Internet线路进行互联,但是使用Internet线路存在安全风险,如何保障数据在传输时不会被窃取?…...
VsCode运行Ts文件
1. 生成package.json文件 npm init 2. 生成tsconfig.json文件 tsc --init 3. Vscode运行ts文件 在ts文件点击右键执行Run Code,执行ts文件...
模型 AITDA(吸引、兴趣、信任、渴望、行动)
系列文章 分享 模型,了解更多👉 模型_思维模型目录。吸引、兴趣、信任、渴望、行动 五步曲。 1 模型AITDA的应用 1.1 开源AI智能名片小程序的营销策略 一家企业开发了开源AI智能名片小程序,旨在通过S2B2C模式连接供应商和消费者。该企业采用…...
十、软件设计架构-微服务-服务调用Feign
文章目录 前言一、Feign介绍1. 什么是Feign2. 什么是Http客户端3. Feign 和 OpenFeign 的区别 二、Feign底层原理三、Feign工作原理详解1. 动态代理机制2. 动态代理的创建过程3. 创建详细流程4. FeignClient属性 四、Feign使用1. 常规调用2.日志打印3. 添加Header 前言 服务调…...
电子商务人工智能指南 3/6 - 聊天机器人和客户服务
介绍 81% 的零售业高管表示, AI 至少在其组织中发挥了中等至完全的作用。然而,78% 的受访零售业高管表示,很难跟上不断发展的 AI 格局。 近年来,电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
