双例集合(三)——双例集合的实现类之TreeMap容器类
Map接口有两个实现类,一个是HashMap容器类,另一个是TreeMap容器类。TreeMap容器类的使用在API上于HashMap容器类没有太大的区别。它们的区别主要体现在两个方面,一个是底层实现方式上,HashMap是基于Hash算法来实现的吗,而TreeMap是基于红黑树来实现的;另一个区别体现在功能上,虽然HashMap容器类的效率比较高,但是它无法实现排序操作。相对的,TreeMap虽然在效率上比不上HashMap,但是它能够实现对双例集合中元素的key进行排序操作。值得注意的是,TreeMap只支持对双例集合中的键key进行排序操作,这个也好理解,因为双例集合中的key与value是一一对应的关系,对key进行排序就相当于也对value进行了排序。
由于TreeMap容器类和HashMap容器类在使用上没有多大的区别,因此我们只要掌握好TreeMap中的排序操作再与HashMap容器类进行对比学习就可以很好地掌握TreeMap容器类了。
TreeMap容器类对键key的排序操作和之前我们介绍的TreeSet容器类对元素的排序操作是相似的。在使用它们的时候都需要给定排序规则,而对于排序规则它们二者都有两种给定排序规则的方式,一种是通过元素自身来实现比较规则,这种方式就是按照元素内定义的规则来实现排序;另一种是通过编程者自定义的比较器来实现比较规则。接下来对TreeMap中的这两种方式进行一一介绍。
首先介绍通过元素自身来实现比较规则的方式。这种方式是按照元素内定义的规则来实现排序的。这里我们用一个例子来进行说明,我们TreeMapTest类中实例化了一个TreeMap容器类对象map,在map对象中我们将它的key设置为类User,value的类型仍然为String,其中User类的代码如下所示。可以发现在User类中我们重写了compareTo方法,这个方法中定义比较规则——按照对象的userAge这个变量的大小进行排序。这时我们在TreeMapTest类中实例化User对象u1,u2和u3,将几个对象作为key添加容器map中去。接下来我们只要遍历容器map中的元素就能发现,它的结果已经按照User中定义的比较规则进行排序了。此处要注意的是,当遇到比较规则中的变量值是相同的情况,则系统会取另一个变量来按照这个新的变量的默认排序规则进行排序。比如在演示代码中我们的对象u2和u3的userAge这个变量的值都是20,那么这个是就会取userName这个变量来进行排序。比较结果为u3在u2的前面,因为按照系统默认的比较规则,字母g在字母l的前面。
package com.container.demo;import java.util.Objects;public class User implements Comparable<User>{private String usersName;private int usersAge;public String getUsersName() {return usersName;}public void setUsersName(String usersName) {this.usersName = usersName;}public int getUsersAge() {return usersAge;}public void setUsersAge(int usersAge) {this.usersAge = usersAge;}@Overridepublic String toString() {return "User{" +"usersName='" + usersName + '\'' +", usersAge=" + usersAge +'}';}public User(String usersName, int usersAge) {this.usersName = usersName;this.usersAge = usersAge;}public User() {}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user = (User) o;return usersAge == user.usersAge && Objects.equals(usersName, user.usersName);}@Overridepublic int hashCode() {return Objects.hash(usersName, usersAge);}//定义比较规则//正数:大,负数:小,0:相等@Overridepublic int compareTo(User o) {if(this.usersAge > o.usersAge)return 1;if(this.usersAge == o.usersAge){return this.usersName.compareTo(o.getUsersName());}return -1;}
}

接下来介绍使用自定义的比较器来实现排序的方法。这里我们仍然以一个例子来进行说明。首先在TreeMapTest类中实例化一个TreeMap容器类对象map1。我们把类Student类作为容器map1中key的类型,Sudent类的代码如下所示。将Student类和上面个的User类进行比较能够发现,在Student类中并没有重写compareTo方法,因此这个类中并没有实现排序规则。和上面一样我们也实例化了3个Student对象,将其添加到容器map1中,这时因为我们没有定义比较器,Student类中也没有实现比较规则,所以如果我们运行程序,那么程序就会在运行时报错提醒我们没有定义key的排序规则。如下图所示:

所以我们需要定义一个比较器,并将它使用到容器map1中。这里我们定义比较器StudentComparator,它的实现代码如下所示。原理就是比较器StudentComparator实现了接口Comparator,然后在这个比较器中重写了compare方法。定义比较器之后我们就需要将比较器应用到map1容器中,应用的方法和TreeSet容器类中应用比较器到容器中是一样的。TreeMap容器类的构造方法中提供了一个有参构造,这个参数就是比较器。所以我们只需要在实例化容器的时候将比较器作为参数传入构造方法中就能应用比较器到容器中了。这里要注意传入参数的形式,因为比较器的实质是一个非静态类,因此在另一个类中使用时需要进行实例化操作,为了方便我们只需要在需要传入参数的地方进行new 操作即可,不需要对实例化的对象进行实际接收。
package com.container.demo;
//比较器
import java.util.Comparator;
public class StudentComparator implements Comparator<Student> {//定义比较规则@Overridepublic int compare(Student o1, Student o2) {if(o1.getAge() >o2.getAge()){return 1;}if(o1.getAge() == o2.getAge()){return o1.getName().compareTo(o2.getName());}return -1;}}
import java.util.Objects;public class Student {private String name;private int age;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Student(String name, int age) {this.name = name;this.age = age;}public Student() {}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
package com.container.demo;import java.util.Map;
import java.util.Set;
import java.util.TreeMap;public class TreeMapTest {public static void main(String[] args) {//实例化TreeMap容器Map<User,String> map = new TreeMap<>();User u1 = new User("linyi",18);User u2 = new User("linling",20);User u3 = new User("lingzi",20);map.put(u1,"liyi");map.put(u2,"linling");map.put(u3,"lingzi");Set<User> keys = map.keySet();for (User key:keys) {System.out.println(key+"---"+map.get(key));}System.out.println("___________________________________");Map<Student,String> map1 = new TreeMap<>(new StudentComparator());Student s1 = new Student("linyi",18);Student s2 = new Student("linling",20);Student s3 = new Student("linger",20);map1.put(s1,"linyi");map1.put(s2,"linling");map1.put(s3,"linger");Set<Student> keys1 = map1.keySet();for (Student key:keys1) {System.out.println(key+"--------"+map1.get(key));}}
}
相关文章:
双例集合(三)——双例集合的实现类之TreeMap容器类
Map接口有两个实现类,一个是HashMap容器类,另一个是TreeMap容器类。TreeMap容器类的使用在API上于HashMap容器类没有太大的区别。它们的区别主要体现在两个方面,一个是底层实现方式上,HashMap是基于Hash算法来实现的吗,…...
[SAP ABAP] 运算符
1.算数运算符 算术运算符描述加法-减法*乘法/除法MOD取余 示例1 输出结果: 输出结果: 2.比较运算符 比较运算符描述示例 等于 A B A EQ B <> 不等于 A <> B A NE B >大于 A > B A GT B <小于 A < B A LT B >大于或等于 A > B A GE B <小…...
MSPM0G3507 ——GPIO例程讲解2——simultaneous_interrupts
主函数: #include "ti_msp_dl_config.h"int main(void) {SYSCFG_DL_init();/* Enable Interrupt for both GPIOA and GPIOB ports */NVIC_EnableIRQ(GPIO_SWITCHES_GPIOA_INT_IRQN); //启用SWITCHES——A的中断 NVIC_EnableIRQ(GPIO_S…...
某程序员:30岁了,老婆管钱,背着我买了50万股票,亏了20w,强制她清仓后又买了36万
“辛辛苦苦攒了几年钱,本想买房买车,结果全被老婆炒股亏掉了!” 近日,一位30岁的程序员大哥在网上吐苦水,引发了网友们的热议。 这位程序员大哥和妻子结婚后,一直秉持着“男主外,女主内”的传统…...
Docker常见面试题整理
文章目录 1. Docker 是什么?它解决了什么问题?2. Docker 和虚拟机(VM)的区别是什么?3、Docker三个核心概念4、如何构建一个 Docker 镜像?5、如何将一个 Docker 容器连接到多个网络?6、Docker Co…...
35 - 最后一个能进入巴士的人(高频 SQL 50 题基础版)
35 - 最后一个能进入巴士的人 -- sum(weight) over(order by turn) as total,根据turn升序,再求前面数的和 selectperson_name from(selectperson_name,sum(weight) over(order by turn) as totalfromQueue) new_Queue wheretotal<1000 order by total desc lim…...
WPF将dll文件嵌入到exe文件中
WPF将dll文件嵌入到exe文件中 第一步:打开.csproj文件,在Import节点后添加如下代码: <Target Name"AfterResolveReferences"><ItemGroup><EmbeddedResource Include"(ReferenceCopyLocalPaths)" Condit…...
2024年AI+游戏赛道的公司和工具归类总结
随着人工智能技术的飞速发展,AI在游戏开发领域的应用越来越广泛。以下是对2024年AI+游戏赛道的公司和工具的归类总结,涵盖了从角色和场景设计到音频制作,再到动作捕捉和动画生成等多个方面。 2D与3D创作 2D创作工具:专注于角色和场景的平面设计,提供AI辅助的图案生成和风…...
svm和决策树基本知识以及模型评价以及模型保存
svm和决策树基本知识以及模型评价以及模型保存 文章目录 一、SVM1.1,常用属性函数 二、决策树2.1,常用属性函数2.2,决策树可视化2.3,决策树解释 3,模型评价3.1,方面一(评价指标)3.2&…...
C++ 79 之 自己写异常类
#include <iostream> #include <string> using namespace std;class MyOutOfRange : public exception{ // 选中exception右键 转到定义 复制一份 virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW 进行函数重写 public: string m_msg;M…...
如何搭建一个成功的短剧制作平台
要搭建一个成功的短剧制作平台,需要考虑多个方面,包括目标定位、技术选择、内容管理、用户体验等。 1、明确目标和定位: 确定你的目标受众是谁,他们的年龄、兴趣、消费习惯等。 明确短剧制作平台的主要定位,是提供原创…...
kotlin类
一、定义 1、kotlin中使用关键字class 声明类,如果一个类没有类体,也可以省略花括号, 默认为public 类型的: // 这段代码定义了一个公开的、不可被继承的Test类 class Test{} // 没有类体,可以省略花括号 class Test 底层代码&…...
android | studio的UI布局和代码调试 | UI调试 (用于找到项目源码)
网上找到一个项目,想快速的搞懂是怎么实现的,搞了半天发现原来android都升级到Jetpack Compose了,然后去找源码挺不容易的,摸索中发现了这个调试的方法,还可以。 https://developer.android.com/studio/debug/layout-i…...
LangChain实战技巧之六:一起玩转config(上篇)——ConfigurableField
简介 Config 包含两大类内容, ConfigurableField 可配置的字段 configurable_alternatives 可配置的替代方案 分别使用两篇文章来给大家介绍,本篇先介绍ConfigurableField 常规介绍 一些资料会这样介绍 model_spec model.configurable_fields(model…...
扫码称重上位机
目录 一 设计原型 二 后台代码 一 设计原型 模拟工具: 二 后台代码 主程序: using System.IO.Ports; using System.Net; using System.Net.Sockets; using System.Text;namespace 扫码称重上位机 {public partial class Form1 : Form{public Form1(){Initialize…...
操作系统入门 -- 进程的通信方式
操作系统入门 – 进程的通信方式 1.什么是进程通信 1.1 定义 进程通信就是在不同进程之间交换信息。在之前文章中可以了解到,进程之间相互独立,一般不可能互相访问。因此进程之间若需要通信,则需要一个所有进程都认可的共享空间࿰…...
Python读取wps中的DISPIMG图片格式
需求: 读出excel的图片内容,这放在微软三件套是很容易的,但是由于wps的固有格式,会出现奇怪的问题,只能读出:类似于 DISPIMG(“ID_2B83F9717AE1XXXX920xxxx644C80DB1”,1) 【该DISPIMG函数只有wps才拥有】 …...
elasticsearch的入门与实践
Elasticsearch是一个基于Lucene构建的开源搜索引擎。它提供了一个分布式、多租户能力的全文搜索引擎,具有HTTP web接口和无模式的JSON文档。以下是Elasticsearch的入门与实践的基本步骤: 入门 安装Elasticsearch: 从Elasticsearch官网下载对…...
神经网络学习6-线性层
归一化用的较少 正则化用来解决过拟合,处理最优化问题,批量归一化加快速度 正则化(Regularization): 作用:正则化是一种用来防止过拟合的技术,通过向模型的损失函数中添加惩罚项,使…...
PHP框架详解 - CodeIgniter 框架
CodeIgniter 是一个成熟的轻量级 PHP 框架,专为小到中型的 Web 应用开发设计。它以其简洁、灵活和易于学习的特点而受到开发者的喜爱。 CodeIgniter 框架的特点包括: 轻量级:CodeIgniter 的核心非常小,加载速度快,适…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
