Java中的Map【二】SortedMap接口

野性酷女 2021-09-20 23:06 807阅读 0赞

所使用的jdk版本为1.8版本,先看一下SortedMap在JDK中Map的UML类图中的位置:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyMDc2MzQ1_size_16_color_FFFFFF_t_70

2.1.2 SortedMap接口

  1. SortedMap<K,V>继承Map<K,V>接口,是一个更进一步提供基于键key的总体排序的 Map。该映射是根据其键key的自然顺序(自然排序的定义可以参见java.lang.Comparable接口,就是实现该接口)进行排序的,或者根据通常在创建有序映射SortedMap时提供的 Comparator 进行排序。
  2. 插入有序映射的所有键都必须实现Comparable接口(或者被指定的比较器Comparator接受)。另外,所有这些键都必须是可互相比较的:对有序映射中的任意两个键k1k2,执行k1.compareTo(k2)(或comparator.compare(k1, k2))都不得抛出ClassCastException。试图违反此限制将导致有问题的的方法或者构造方法调用抛出ClassCastException
  3. SortedMap<K,V>接口从定义来看比较简单,需要注意的就是其中的key要么实现Comparable接口要么被指定的比较器Comparator接受。接口定义描述建议所有的SortedMap实现类都应该提供四个标准的构造函数:

(1)void 无参的构造函数,此时按照键的自然顺序进行排序;

(2)只有一个 Comparator 类型参数的构造方法,它创建一个空的有序映射,并且根据指定的 Comparator进行排序;

(3)只有一个 Map 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系与参数Map相同,按照键的自然顺序进行排序;

(4)只有一个 SortedMap 类型参数的构造方法,它创建一个新的有序映射,其键-值映射关系和排序方法与入参的SortedMap相同。

因为接口中无法定义构造方法,无法保证以上四种方法一定就会被实现。最上面的图,SortedMap实现类TreeMap是全部实现了这四个构造方法的。

因为SortedMap定义相对简单,简单列一些里面的函数:

  1. public interface SortedMap<K,V> extends Map<K,V> {
  2. /**
  3. * 返回对此映射中的键进行排序的比较器;如果使用的自然顺序,返回null
  4. */
  5. Comparator<? super K> comparator();
  6. /**
  7. * 返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。(如果 fromKey
  8. * 和 toKey 相等,则返回映射为空。)返回的映射受此映射支持,所以在返回映射中的更改将反映在此
  9. * 映射中,反之亦然。返回的映射支持此映射支持的所有可选映射操作。
  10. * 如果试图在返回映射的范围之外插入键,则返回的映射将抛出 IllegalArgumentException。
  11. *
  12. * @param fromKey - 返回映射中key的低端点(包括)
  13. * @param toKey - 返回映射中键的高端点(不包括)
  14. * @return 此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)
  15. * @throws ClassCastException - 如果无法使用此映射的比较器(如果此映射没有比较器,则使用
  16. * 自然顺序)比较 fromKey 和 toKey。如果 fromKey 或 toKey 不能与映射中当前键进行比较,则
  17. * 实现可以(但不是必须)抛出此异常。
  18. * @throws NullPointerException - 如果 fromKey 或 toKey 为 null,并且此映射不允许使
  19. * 用 null 键
  20. * @throws IllegalArgumentException - 如果 fromKey 大于 toKey;如果此映射本身有范围限
  21. * 制,并且 fromKey 或 toKey 位于范围的边界之外
  22. */
  23. SortedMap<K,V> subMap(K fromKey, K toKey);
  24. /**
  25. * 返回此映射的部分视图,其键值严格小于 toKey。返回的映射受此映射支持,所以在返回映射中的更改
  26. * 将反映在映射中,反之亦然。返回的映射支持此映射支持的所有可选映射操作。
  27. *
  28. * 如果试图在返回映射的范围之外插入键,则返回的映射将抛出 IllegalArgumentException。
  29. *
  30. * @param toKey 返回映射视图中键的高端点(不包括)
  31. * @return 此映射的部分视图,且其中的键严格小于 toKey
  32. * @throws ClassCastException 如果 toKey 与此映射的比较器不兼容(或者,如果该映射没有比
  33. * 较器, 如果 toKey 没有实现 Comparable)。如果 toKey 不能与映射中的当前键进行比较,则实
  34. * 现可以(但不是必须)抛出此异常。
  35. * @throws NullPointerException 如果toKey为null,且该映射不允许key为null
  36. * @throws IllegalArgumentException 如果此映射本身有范围限制,并且 toKey 位于范围的边界
  37. * 之外
  38. */
  39. SortedMap<K,V> headMap(K toKey);
  40. /**
  41. * 返回此映射的部分视图,其键大于等于 fromKey。返回的映射受此映射支持,所以在返回映射中的更改
  42. * 将反映在映射中,反之亦然。返回的映射支持此映射支持的所有可选映射操作。
  43. * 如果试图在返回映射的范围之外插入键,则返回的映射将抛出 IllegalArgumentException。
  44. *
  45. * @param fromKey 返回映射中键的低端点(包括)
  46. * @return 此映射的部分视图,其中的键大于等于 fromKey
  47. * @throws ClassCastException 如果 fromKey 与此映射的比较器不兼容(或者,如果该映射没有
  48. * 比较器;如果 fromKey 没有实现 Comparable)。如果 fromKey 不能与映射中的当前键进行比
  49. * 较,则实现可以(但不是必须)抛出此异常。
  50. * @throws NullPointerException 如果 fromKey 为 null,并且此映射不允许使用 null 键
  51. * @throws IllegalArgumentException 如果此映射本身有范围限制,并且 fromKey 位于范围的
  52. * 边界之外
  53. */
  54. SortedMap<K,V> tailMap(K fromKey);
  55. /**
  56. * 返回此映射中当前第一个(最低)键。
  57. *
  58. * @return 返回此映射中当前第一个(最低)键。
  59. * @throws NoSuchElementException 如果map为空(即size() == 0)
  60. */
  61. K firstKey();
  62. /**
  63. * 返回映射中当前最后一个(最高)键。
  64. *
  65. * @return 返回映射中当前最后一个(最高)键。
  66. * @throws NoSuchElementException 如果map为空(即size() == 0)
  67. */
  68. K lastKey();
  69. /**
  70. * 与父接口Map中的定义一样,但有顺序
  71. */
  72. Set<K> keySet();
  73. /**
  74. * 与父接口Map中的定义一样,但有顺序(根据key的顺序)
  75. */
  76. Collection<V> values();
  77. /**
  78. * 与父接口Map中的定义一样,但有顺序(根据key的顺序)
  79. */
  80. Set<Map.Entry<K, V>> entrySet();
  81. }

需要注意的地方:

1、subMap(K fromKey, K toKey)、headMap(K toKey)、tailMap(K fromKey),都是满足fromKey <= key < toKey;

2、firstKey()和lastKey()方法,当SortedMap对象为空(size() == 0)就会抛出NoSuchElementException异常;

3、subMap等子集map和当前sortedMap的元素变更是互相影响的。

以上注意点可以用TreeMap实现验证(后续会分析在TreeMap中的实现):

  1. public static void main(String[] args) {
  2. SortedMap<Integer, Integer> sortedMap = new TreeMap();
  3. sortedMap.put(2,2);
  4. sortedMap.put(4,4);
  5. sortedMap.put(1,1);
  6. System.out.println(sortedMap.subMap(1,2));
  7. System.out.println(sortedMap.headMap(2));
  8. System.out.println(sortedMap.tailMap(2));
  9. //获取的子集中添加一个元素会影响当前sortedMap
  10. SortedMap<Integer, Integer> subSortedMap = sortedMap.subMap(0,4);
  11. subSortedMap.put(3,3);
  12. //当前sortedMap增减元素会影响子集subSortedMap
  13. sortedMap.put(0,0);
  14. System.out.println(subSortedMap);
  15. System.out.println(sortedMap);
  16. }

程序输出结果:

  1. {1=1}
  2. {1=1}
  3. {2=2, 4=4}
  4. {0=0, 1=1, 2=2, 3=3}
  5. {0=0, 1=1, 2=2, 3=3, 4=4}

以上,SortedMap暂时写这么多~

题外话:这里发现一个值得玩味的地方,就是keySet()、values()、entrySet()三个方法在父接口Map已经有相同结构的方法定义了,在SortedMap中又重新定义了一次(不过返回的都是有顺序的)。JDK中还有很多类似这样子接口重新定义了父接口中方法情况,比如List接口中定义了和父接口Collection一样的size()、isEmpty()等,感觉这种更多是处于软件工程和设计模式等方面的考虑吧,不知诸位对此有何看法,欢迎留言赐教~

发表评论

表情:
评论列表 (有 0 条评论,807人围观)

还没有评论,来说两句吧...

相关阅读

    相关 javaMap接口

    java中的Map接口 实现Map接口的类用来存储——键值对 Map接口的实现类有HashMap和TreeMap等 键值不能重复(键相当与索引)  TestMap.

    相关 Java SortedMap 接口

    Java 集合框架的SortedMap接口提供了对存储在映射中的键的排序。 它扩展了Map 接口。 Java SortedMap 接口扩展了 Map 接口。 实现 ...