【达内课程】集合之 TreeMap

2024-05-12 10:18
文章标签 集合 课程 treemap

本文主要是介绍【达内课程】集合之 TreeMap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • TreeMap
  • Treemap 特有方法
  • 举例:TreeMap使用练习
  • 举例:用销售额模型练习使用 Comparable
  • 比较器

TreeMap

介绍
我们已经知道,HashMap 是一种以空间换时间的映射表,它的实现原理决定了内部的 Key 是无序的,即遍历 HashMap 的 Key 时,其顺序是不可预测的(但每个 Key都会遍历一次且仅遍历一次)。

还有一种 Map,它在内部会对 Key 进行排序,这种 Map 就是 SortedMap。注意到 SortedMap 是接口,它的实现类是 TreeMap。

SortedMap 保证遍历时以 Key 的顺序来进行排序。例如,放入的 Key 是 “apple”、“pear”、“orange”,遍历的顺序一定是 “apple”、“orange”、“pear”,因为 String 默认按字母排序。

创建对象

TreeMap map = new TreeMap();
TreeMap map = new TreeMap(比较器);

Treemap 特有方法

Treemap 的方法是在 Hashmap 的基础上进行补充的,下面介绍的是 Treemap 里的特有方法,至于基础方法和 Hashmap 一模一样,只是没有 compute 和 merge。

1、查找限定范围内的一个 key 或 entry,之所以会有这些方法,是因为 Treemap 是有序的。

firstKey() //查找map中最小的键(第一个)
lastKey() 查找map中最大的键(最后一个)
higherKey() //大于这个 key 的键
lowerKey() //大于这个 key 的键
ceilingKey(k key) //大于等于这个key的元素
floorKey(K key) //返回小于等于给定键的最大键;如果不存在这样的键,则返回null

firstEntry() //返回集合中的第一个元素
lastEntry() //返回集合中的最后的元素
higherEntry() //返回一个最小键大于key的条目;如果没有这样的键,则返回null
lowerEntry() //返回最大键小于键的条目;如果没有这样的键,则返回null
ceilingEntry() //返回与该键至少大于或等于给定键,如果不存在这样的键的键 - 值映射,则返回null相关联
lowerEntry() //返回该 map 中小于指定 key 的最大的 key-value 键值对,若 map 为空,则返回为null

2、删除最大或最小键值对
pollFirstEntry() //返回并删除与此TreeMap中存在的最低键元素值链接的条目(键值对)
pollLastEntry() //回然后删除与此TreeMap中存在的最大键元素值链接的条目(键值对)

3、获取 Treemap 的子集或 变种
descendingKeySet //返回集合的全部Key,并且是逆序的
descendingMap //把集合逆序返回
subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) //截取集合中 Key 从 fromKey 到 toKey 的元素,否是截取他们本身,取决于 true 或者 false
subMap(K fromKey, K toKey) //截取集合中 Key 从 fromKey 到 toKey 的元素,包括 fromKey,不包括 toKey
tailMap(K fromKey, boolean inclusive) // 当 inclusive 为 true 时,截取 Key 大于等于 fromKey 的所有元素,否则截取 Key 大于 fromKey 的所有元素
tailMap(K fromKey) //截取 Key 大于等于 fromKey 的所有元素
headMap(K toKey, boolean inclusive) //当 inclusive 为 true 时,就是返回 Key 小于等于 toKey 的所有元素
headMap(K toKey) //返回 Key 小于 toKey 的所有元素

举例:TreeMap使用练习

TreeMap<Integer, String> map = new TreeMap<>();
map.put(999, "9");
map.put(555, "5");
map.put(777, "7");
map.put(222, "2");
map.put(666, "6");
map.put(888, "8");
map.put(333, "3");
map.put(111, "1");
System.out.println(map.size());//8
System.out.println(map);//{111=1, 222=2, 333=3, 555=5, 666=6, 777=7, 888=8, 999=9}
System.out.println(map.get(666));//6
System.out.println(map.containsKey(999));//true
System.out.println(map.containsValue("9"));//true
System.out.println(map.remove(222));//2
System.out.println(map);//{111=1, 333=3, 555=5, 666=6, 777=7, 888=8, 999=9}

从打印结果可以看出是 TreeMap 是按照键值从小到大的顺序排列的。

举例:用销售额模型练习使用 Comparable

我们用横坐标代表月份,纵坐标代表销售额:
(1,35)表示1月份销售3.5亿
(2,42)表示2月份销售4.2亿

然后将这两个坐标点放入一个 TreeMap 中,键放入坐标点,值放入表示的销售额字符串。新建 Point 类来表示坐标点。

Point 类

class Point {private int x;private int y;public Point() {super();}public Point(int x, int y) {super();this.x = x;this.y = y;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}@Overridepublic boolean equals(Object obj) {if (obj == null) return false;if (obj == this) return true;if (!(obj instanceof Point)) return false;Point p = (Point) obj;returnthis.x == p.x && this.y == p.y;}@Overridepublic String toString() {return "(" + x + "," + y + ")";}
}

Main.java

public class Main {public static void main(String[] args) {//分别代表月份和销售额//1月销售3.5亿/横坐标1,纵坐标35//2月销售4.2亿/横坐标2,纵坐标42Point a = new Point(1, 35);Point b = new Point(2, 42);//(键是坐标,值是字符串)//(Point,String)TreeMap<Point, String> map = new TreeMap<>();map.put(a, "3.5亿");map.put(b, "4.2亿");System.out.println(map);}
}

运行结果

Exception in thread “main” java.lang.ClassCastException: class com.company.Point cannot be cast to class java.lang.Comparable (com.company.Point is in unnamed module of loader ‘app’; java.lang.Comparable is in module java.base of loader ‘bootstrap’)
at java.base/java.util.TreeMap.compare(TreeMap.java:1291)
at java.base/java.util.TreeMap.put(TreeMap.java:536)
at com.company.Main.main(Main.java:16)

这样写会出错的原因是,放入 TreeMap 的键是要比较大小的,小的放在左边,大的放在右边。

使用 TreeMap 时,放入的 Key 必须实现 Comparable 接口。String、Integer 这些类已经实现了 Comparable 接口,因此可以直接作为 Key 使用。作为 Value 的对象则没有任何要求。

知道了这点,所以 Point 必须实现 Comparable 接口,因此修改Point类

class Point implements Comparable<Point> {......(同上)/** 当前对象与参数对象o比较大小* 当前对象大,正数* 当前对象小,负数* 相同,0*/@Overridepublic int compareTo(Point o) {//这里按照月份比较大小,return x - o.x;}
}

运行结果

{(1,35)=3.5亿, (2,42)=4.2亿}

比较器

比较大小有两种方式
1、实现 Comparable 接口
2、外接 Comparator 比较器(优先执行)

如果作为 Key 的 class 没有实现 Comparable 接口,那么,必须在创建 TreeMap 时同时指定一个自定义排序算法:

public class Main {public static void main(String[] args) {Point a = new Point(1, 35);Point b = new Point(2, 42);//接口是不能创建实例的,但可以创建匿名类的实例Comparator<Point> comparator = new Comparator<Point>() {/** o1 o2比较大小* o1大 正数* o1小 负数* 相同 0*/@Overridepublic int compare(Point o1, Point o2) {//TreeMap的排序规则是从小到大//但是我们的要求是按照销售额从大到小排列//所以反过来相减return o2.getY() - o1.getY();}};//(键是坐标,值是字符串)//(Point,String)TreeMap<Point, String> map = new TreeMap<>(comparator);map.put(a, "3.5亿");map.put(b, "4.2亿");System.out.println(map);}
}

之前结果

{(1,35)=3.5亿, (2,42)=4.2亿}

之后结果

{(2,42)=4.2亿, (1,35)=3.5亿}

注意到Comparator接口要求实现一个比较方法,它负责比较传入的两个元素 a 和 b,如果 a<b,则返回负数,通常是 -1,如果 a==b,则返回 0,如果 a>b,则返回正数,通常是 1。TreeMap 内部根据比较结果对 Key 进行排序。

有比较器执行比较器,没有比较器执行 Comparable

其中 TreeMap 的比较器是我们自己程序实现的,然后被 TreeMap 内部调用,这种实现模式称为回调模式 Callback

参考
java中TreeMap常用方法

这篇关于【达内课程】集合之 TreeMap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/982344

相关文章

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

Java基础回顾系列-第六天-Java集合

Java基础回顾系列-第六天-Java集合 集合概述数组的弊端集合框架的优点Java集合关系图集合框架体系图java.util.Collection接口 List集合java.util.List接口java.util.ArrayListjava.util.LinkedListjava.util.Vector Set集合java.util.Set接口java.util.HashSetjava

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

java集合的概述

集合就是一个容器,我们可以把多个对象放入的容器中。就像水杯(假设容量可以不断扩大)一样,你可以往水杯中不断地添加水,既然是水杯,你就不能往里添加沙子,也就是说集合中添加的对象必须是同一个类型的(引用类型,而不能是基本类型)。 看到集合的介绍会让我们的想起数组,那么集合和数组有什么区别呢? 首先,数组的大小是固定的,而集合理论上大小是不限的。 其次,数组既可以存储基本数据类型的数据,也可以存储

《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》P98

更改为 差分的数学表达式从泰勒级数展开式可得: 后悔没听廖老师的。 禹晶、肖创柏、廖庆敏《数字图像处理(面向新工科的电工电子信息基础课程系列教材)》 禹晶、肖创柏、廖庆敏《数字图像处理》资源二维码

hutool 集合相关交集、差集

开发过程中会遇到集合之间的对比之类的需求,之前经常会自己写个工具类来实现,目前hutool可以帮助我们解决很多问题,接下来我们就来实践下。 相关jar包 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>RELEASE</version><scope>compile</sco

Java8中的Stream,让集合操作酸爽起来

简介 java8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到集合,遍历集合可以试下lambda表达式,经常还要对集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。 Stream作为java8的新特性,基于lambda表达式,是对集合对象功能的增强,它专注于对集合对象进行各种高效、便利的聚合

算法练习小技巧之有序集合--套路详细解析带例题(leetcode)

前言:         本文详细讲解Python中的有序集合SortedList和C++中的有序集合multiset的用法,配合leetcode的例题来展示实际的用处。(本人水平不够,还无法讲解有序集合的实现方法,只会用)         觉得有帮助或者写的不错可以点个赞,后面也有几道我找出来的题目可以用这个方法快速解决的         (感觉有点水) 目录 有序集合用法讲解:

Java中集合类Set、List和Map的区别

Java中的集合包括三大类,它们是Set、List和Map,它们都处于java.util包中,Set、List和Map都是接口,它们有各自的实现类。Set的实现类主要有HashSet和TreeSet,List的实现类主要有ArrayList,Map的实现类主要有HashMap和TreeMap。那么它们有什么区别呢? Set中的对象不按特定方式排序,并且没有重复对象。但它的有些实现类能对集合中的对

复杂SQL集合(不断收集中)

1.一道SQL语句面试题,关于group by 表内容: 2005-05-09 胜 2005-05-09 胜 2005-05-09 负 2005-05-09 负 2005-05-10 胜 2005-05-10 负 2005-05-10 负 如果要生成下列结果, 该如何写sql语句?             胜 负 2005-05-09 2 2 2005-05-10 1 2 --------