本文主要是介绍【达内课程】集合之 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!