8.6.5 SortedMap接口和TreeMap实现类
8.6.5 SortedMap接口和TreeMap实现类
正如Set
接口派生出SortedSet
子接口有一个TreeSet
实现类一样,Map
接口也派生的SortedMap
子接口也有一个TreeMap
实现类.
TreeMap数据结构 红黑树
TreeMap
就是一个红黑树
数据结构,每个key-value
对即作为红黑树的一个节点。 TreeMap
存储key-value
对(节点)时,需要根据key
对节点进行排序。 TreeMap
可以保证所有的key-value
对处于有序状态。
自然排序 定制排序
TreeMap
也有两种排序方式:
- 自然排序:
TreeMap
的所有key
必须实现Comparable
接口,而且所有的key
应该是同一个类的对象,否则将会抛出ClassCastException
异常。 - 定制排序:创建
TreeMap
时,传入一个Comparator
对象,该对象负责对TreeMap
中的所有key
进行排序。采用定制排序时不要求Map
的key
实现Comparable
接口。
TreeMap判断两个key相等的标准
类似于TreeSet
中判断两个元素相等的标准, TreeMap
中判断两个key
相等的标准是:
如果两个key
通过compareTo()
方法返回0
, 那么TreeMap
就认为这两个key
是相等的。
理解Comparable接口的compareTo方法
- 如果
对象.compareTo(参数)
返回0,则表示该对象和参数相等. - 如果
对象.compareTo(参数)
返回正数,则表示该对象大于参数. - 如果
对象.compareTo(参数)
返回负数,则表示该对象小于参数.
为了便于记忆可以把Comparable
接口的compareTo
方法理解为减去
的意思,也就是说对象.compareTo(参数)
意思为对象减去参数
.
- 如果对象减去参数等于
0
,则两者相等. - 如果对象减去参数大于0,则对象大于参数,
- 如果对象减去参数小于0则对象小于参数。
理解Comparator接口的compare方法
同样的Comparator
接口的compare(参数1,参数2)
可以理解为前面的参数减去后面的参数
的计算结果.也就是参数1减去
参数2,所以:
- 如果参数1减去参数2等于0时,两者相等,
- 如果参数1减去参数2大于0,则参数1大于参数2,
- 如果参数1减去参数2小于0,则参数1小于参数2.
作为key的自定义类的要求
如果使用自定义类作为TreeMap
的key
,且想让TreeMap
良好地工作,则重写该类的equals()
方法和compareTo()
方法时应保持一致的返回结果:
**两个key
通过equals
方法比较返回true
时,它们通过compareTo()
方法比较应该返回0
**。如果equals()
方法与compareTo()
方法的返回结果不一致, TreeMap
与Map
接口的规则就会冲突。
Java使用Map来实现的Set
再次强调:Set
和Map
的关系十分密切,Java
源码就是先实现了HashMap
、TreeMap
等集合,然后通过包装一个所有的value
都为null
的Map
集合实现了Set
集合类。
Set和Map的关系
再次强调:Set
和Map
的关系十分密切,Java
源码就是先实现了HashMap
、 TreeMap
等集合,然后通过包装一个所有的value
都为null
的Map
集合来实现Set
集合类。
返回key或Entry的方法
与TreeSet
类似的是, TreeMap
中也提供了一系列根据key
顺序访问key-value
对的方法。
查找最大最小的key
方法 | 描述 |
---|---|
K firstKey() |
返回该Map 中的最小key 值,如果该Map 为空,则返回null 。 |
K lastKey() |
返回该Map 中的最大key 值,如果该Map 为空或不存在这样的key ,则都返回null 。 |
查找给定key的前一个或后一个key
方法 | 描述 |
---|---|
K higherKey(K key) |
返回该Map 中大于参数key 的最小key 值。如果该Map 为空或不存在这样的key-value 对,则都返回null 。 |
K lowerKey(K key) |
返回该Map 中小于参数key 的最大key 值。如果该Map 为空或不存在这样的key ,则都返回null |
查找最大最小key对应的Entry
方法 | 描述 |
---|---|
Map.Entry<K,V> firstEntry() |
返回该Map 中最小key 所对应的key-value 对,如果该Map 为空,则返回null 。 |
Map.Entry<K,V> lastEntry() |
返回该Map 中最大key 所对应的 key-value 对,如果该Map 为空或不存在这样的key-value 对,则都返回null 。 |
查找给定key的前一个或后一个key对应的Entry
方法 | 描述 |
---|---|
Map.Entry<K,V> higherEntry(K key) |
返回该Map 中大于参数key 的最小key 所对应的key-value 对。如果该Map 为空,则返回null 。 |
Map.Entry<K,V> lowerEntry(K key) |
返回该Map 中小于参数key 的最大key 所对应的key-value 对。如果该Map 为空或不存在这样的 key-value 对,则都返回null |
截取子Map的方法
截取指定区间
方法 | 描述 |
---|---|
SortedMap<K,V> subMap(K fromKey, K toKey) |
返回该Map 的子Map ,其key 的范围是从fromKey (包括)到toKey (不包括)。subXXX() 方法遵循前闭后开 原则。 |
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) |
返回该Map 的子Map ,其key 的范围是从 fromKey 到toKey ,是否包括fromKey 取决于第二个参数,是否包括toKey 取决于第四个参数. |
向前截取
方法 | 描述 |
---|---|
SortedMap<K,V> headMap(K toKey) |
返回该Map 的子Map ,其key 的范围是小于toKey 的所有key ,不包括toKey . |
NavigableMap<K,V> headMap(K toKey, boolean inclusive) |
Returns a view of the portion of this map whose keys are less than (or equal to, if inclusive is true) toKey. |
向后截取
方法 | 描述 |
---|---|
SortedMap<K,V> tailMap(K fromKey) |
返回该Map 的子Map ,其key 的范围是大于fromKey (包括)的所有key 。 |
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) |
返回该Map 的子Map ,其key 的范围是大于fromKey 的所有key ,子Map 是否包括第一个fromKey 取决于第二个参数. |
表面上看起来这些方法很复杂,其实它们很简单。因为TreeMap
中的key-value
对是有序的,所以增加了访问第一个、最后一个、前一个、后一个、key-value
对的方法,并提供了几个从TreeMap
中截取子TreeMap
的方法。
实例
下面以自然排序为例,介绍TreeMap
的基本用法。
1 | import java.util.*; |
上面程序中定义了一个R
类,该类重写了equals
方法,并实现了Comparable
接口,所以可以使用该R对象作为TreeMap
的key
,该TreeMap
使用自然排序。运行上面程序,看到如下运行结果:
1 | {R[count:-5]=疯狂Java讲义, R[count:3]=轻量级Java EE企业应用实战, R[count:9]=疯狂Android讲义} |