SortedMap、NavigableMap、TreeMap介绍和使用

SortedMap、NavigableMap、TreeMap介绍和使用

SortedMap接口:SortedMap是一个接口,继承自Map接口,它定义了对键值对按照键的自然顺序或自定义顺序进行排序的功能。SortedMap中的键值对是按照键的顺序排列的,因此可以根据键的顺序进行范围查找和遍历操作。SortedMap接口提供了一系列的导航方法和有序操作方法。

NavigableMap接口:NavigableMap是SortedMap接口的子接口,它在SortedMap的基础上增加了一些额外的导航方法,使得对有序键值对的操作更加方便和灵活。NavigableMap接口提供了lowerKey、floorKey、ceilingKey、higherKey等导航方法,以及pollFirstEntry、pollLastEntry等移除并返回最小/最大键值对的方法。

TreeMap类:TreeMap是SortedMap接口的实现类,它使用红黑树数据结构来实现有序映射。TreeMap根据键的自然顺序或自定义比较器对键值对进行排序,并保持键值对的有序性。TreeMap提供了对键值对的插入、查找、删除和范围操作等常用功能。

SortedMap

在实际开发中,我们绝大多数用到HashMap,只有极个别情况下,才会使用其他的Map的拓展集合 。

官方介绍:

进一步提供键的总排序的Map。映射根据其键的自然顺序排序,或者由通常在排序映射创建时提供的Comparator排序。这个顺序在迭代排序映射的集合视图时反映出来(由entrySet、keySet和values方法返回)。

提供了几个额外的操作来利用排序。(这个接口是SortedSet的映射模拟。)插入到排序映射中的所有键都必须实现Comparable接口(或被指定的比较器接受)。此外,所有这样的键必须是相互比较的:k1. compareto (k2)(或comparator.compare(k1, k2))不能对排序映射中的任何键k1和k2抛出ClassCastException。试图违反此限制将导致违规方法或构造函数调用抛出ClassCastException。

注意,如果排序映射要正确实现map接口,那么由排序映射维护的排序(无论是否提供显式比较器)必须与equals保持一致。(参见Comparable接口或Comparator接口了解consistent with equals的精确定义。)这是因为Map接口是根据equals操作定义的,但是排序映射使用它的compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,该方法认为相等的两个键是相等的。

树状映射的行为是定义良好的,即使它的顺序与等号不一致;它只是没有遵守Map接口的一般约定。所有通用排序映射实现类都应该提供四个“标准”构造函数。虽然不能通过接口指定必需的构造函数,但不可能强制执行此建议。所有排序映射实现的预期“标准”构造函数是:

  1. 一个void(无参数)构造函数,它创建一个根据键的自然顺序排序的空排序映射。
  2. 具有单个Comparator类型参数的构造函数,它创建一个根据指定的比较器排序的空排序映射。
  3. 具有单个Map类型参数的构造函数,它创建一个具有与其参数相同的键值映射的新映射,并根据键的自然顺序进行排序。
  4. 具有SortedMap类型的单个参数的构造函数,它创建一个新的排序映射,该映射具有与输入排序映射相同的键值映射和相同的顺序。

注意:一些方法返回具有受限键范围的子映射。这些范围是半开的,也就是说,它们包括低点,但不包括高点(在适用的情况下)。如果需要封闭范围(包括两个端点),并且密钥类型允许计算给定密钥的后继值,则只需请求从lowEndpoint到后继值(highEndpoint)的子范围。

例如,假设m是一个键为字符串的映射。下面的习惯用法获取一个视图,其中包含m中键值在low和high之间的所有键值映射,包括:SortedMap<String, V> sub = m. submap (low, high+"\0");可以使用类似的技术来生成一个开放范围(不包含端点)。下面的用法获取一个视图,该视图包含m中所有键值在low和high之间且互斥的键值映射:SortedMap<String, V> sub = m. submap (low+"\0", high);该接口是Java集合框架的成员。

简述

SortedMap就是Java中的一个接口,继承自Map接口,提供了对键值对按照键的自然顺序或者自定义顺序进行排序的功能,SortMap中及那只对是按照键的顺序排序的,因此可以根据键值的顺序进行范围查找和遍历操作。

SortedMap接口的常用实现类是TreeMap,也就是我们标题中的最后一个,使用的是红黑树数据结构来实现有序映射,TreeMap根据键的自然顺序或自定义比较器对键进行排序,并保持键值对的有序性。
在这里插入图片描述

SortedMap 示例

public class SortedMapExample {
    public static void main(String[] args) {
        SortedMap<Integer,String> sortedMap = new TreeMap<>();

        sortedMap.put(3,"Apple");
        sortedMap.put(1,"Banana");
        sortedMap.put(2,"Orange");

        System.out.println(sortedMap); //{1=Banana, 2=Orange, 3=Apple}

        SortedMap<Integer,String> subMap = sortedMap.subMap(1,3);
        System.out.println(subMap); //{1=Banana, 2=Orange}
    }
}

我们创建了一个SortedMap对象,使用TreeMap作为实现类。我们向SortedMap中插入了三个键值对,并输出SortedMap的内容,可以看到键值对按照键的自然顺序排列。

我们还使用subMap方法获取了SortedMap的子映射,范围是从键1(包含)到键3(不包含)。输出子映射的内容,可以看到子映射中的键值对也是按照键的顺序排列的。

SortedMap的优缺点

优点:

  • 有序性:sortedMap保持键值对的有效性,可以根据键的顺序进行范围查找和遍历操作。
  • 提供子映射: SortedMap提供了subMap方法,可以获取原有映射的子映射,方便进行范围操作。
  • 可自定义排序:SortedMap可以根据自然顺序或自定义比较器对键进行排序,灵活性较强。

缺点:

  • 内存占用:相比于普通的HashMap,SortedMap需要额外的内存来维护有效性,因此可能会占用跟多的内存空间。
  • 插入和删除性能略低:由于需要维护有效性,SortedMap在插入和删除元素的时候,相对于普通的HashMap会略微降低性能。

使用场景

  • 当需要按照键的顺序进行范围查找或遍历操作时,可以使用SortedMap。
  • 当需要根据键的顺序对映射进行排序时,可以使用SortedMap。
  • 当需要获取子映射进行范围操作时,可以使用SortedMap。

NavigableMap

官方介绍

SortedMap扩展了导航方法,返回给定搜索目标的最接近匹配项。方法lowerEntry, floorEntry, ceilingEntry, higherEntry返回Map。与键相关联的条目对象分别小于、小于或等于、大于或等于和大于给定键,如果没有这样的键则返回null。类似地,方法lowerKey、floorKey、ceilingKey和higherKey只返回关联的键。所有这些方法都是为定位而设计的,而不是遍历条目。

NavigableMap可以按升序或降序键来访问和遍历。descendingMap方法返回地图的视图,其中所有关系方法和方向方法的含义颠倒。升序操作和视图的性能可能比降序操作和视图的性能快。方法subMap、headMap和tailMap与同名的SortedMap方法的不同之处在于,它们接受描述下界和上界是包含还是排斥的附加参数。

任何NavigableMap的子映射都必须实现NavigableMap接口。该接口还定义了方法firstEntry、pollFirstEntry、lastEntry和pollLastEntry,它们返回或删除最小和最大映射(如果存在的话),否则返回null。入口返回方法的实现期望返回Map。条目对表示生成映射时的快照,因此通常不支持可选的条目。setValue方法。但是请注意,可以使用put方法更改关联映射中的映射。方法subMap(K, K), headMap(K)和tailMap(K)被指定返回SortedMap,以允许SortedMap的现有实现被兼容地改造以实现NavigableMap,但鼓励此接口的扩展和实现覆盖这些方法以返回NavigableMap。类似地,可以重写keySet()以返回NavigableSet。该接口是Java集合框架的成员。

简述

在Java中,NavigableMap是SortedMap接口的子接口,它提供了一系列用于导航和操作有序键值对的方法。NavigableMap在SortedMap的基础上增加了一些额外的导航方法,使得对有序映射的操作更加方便和灵活。

在这里插入图片描述

常用的导航方法:

  • lowerKey(K key) :返回小于给定键的最大键,如果不存在则返回null。
  • floorKey(K key) :返回小于等于给定键的最大键,如果不存在则返回null。
  • ceilingKey(K key):返回大于等于给定键的最小键,如果不存在则返回null。
  • higherKey(K key):返回大于给定键的最小键,如果不存在则返回null。
  • pollFirstEntry():移除并返回最小的键值对,如果映射为空则返回null。
  • pollLastEntry():移除并返回最大的键值对,如果映射为空则返回null。
  • descendingMap():返回一个与原有映射相反顺序的NavigableMap。

NavigableMap的常用实现类是TreeMap,它实现了NavigableMap接口,并使用红黑树数据结构来实现有序映射。通过NavigableMap的导航方法,我们可以方便地进行范围查找、获取最小/最大键值对、移除最小/最大键值对等操作。

示例

public class NavigableMapExample {
    public static void main(String[] args) {
        NavigableMap<Integer, String> navigableMap = new TreeMap<>();

        navigableMap.put(1, "Apple");
        navigableMap.put(3, "Banana");
        navigableMap.put(5, "Orange");
        navigableMap.put(7, "Grapes");

        System.out.println(navigableMap); // 输出:{1=Apple, 3=Banana, 5=Orange, 7=Grapes}

        System.out.println(navigableMap.lowerKey(4)); // 输出:3
        System.out.println(navigableMap.floorKey(4)); // 输出:3
        System.out.println(navigableMap.ceilingKey(4)); // 输出:5
        System.out.println(navigableMap.higherKey(4)); // 输出:5

        System.out.println(navigableMap.pollFirstEntry()); // 输出:1=Apple
        System.out.println(navigableMap.pollLastEntry()); // 输出:7=Grapes

        System.out.println(navigableMap.descendingMap()); // 输出:{5=Orange, 3=Banana}
    }
}

output:
{1=Apple, 3=Banana, 5=Orange, 7=Grapes}
3
3
5
5
1=Apple 7=Grapes
{5=Orange, 3=Banana}

我们创建了一个NavigableMap对象,使用TreeMap作为实现类。我们向NavigableMap中插入了四个键值对,并输出NavigableMap的内容。

然后,我们使用NavigableMap的导航方法进行范围查找和获取最小/最大键值对的操作。我们还使用pollFirstEntry和pollLastEntry方法移除并返回最小/最大的键值对。最后,我们使用descendingMap方法获取与原有映射相反顺序的NavigableMap。

优缺点和使用场景

优点

  • 导航功能:NavigableMap提供了一系列导航方法,如lowerKey、floorKey、ceilingKey、higherKey等,使得对有序键值对的范围查找和导航操作更加方便和灵活。

  • 有序性:NavigableMap保持键值对的有序性,可以根据键的顺序进行范围查找、遍历和操作。

  • 提供子映射:NavigableMap提供了subMap、headMap和tailMap等方法,可以获取原有映射的子映射,方便进行范围操作。

  • 可自定义排序:NavigableMap可以根据自然顺序或自定义比较器对键进行排序,灵活性较高。

缺点

  • 内存占用:相比于普通的HashMap,NavigableMap需要额外的内存来维护有序性,因此可能占用更多的内存空间。

  • 插入和删除性能略低:由于需要维护有序性,NavigableMap在插入和删除元素时,相对于普通的HashMap会略微降低性能。

使用场景

  • 当需要对有序键值对进行范围查找、遍历和操作时,可以使用NavigableMap。
  • 当需要获取最小/最大键值对或根据键的顺序进行导航操作时,可以使用NavigableMap。
  • 当需要获取子映射进行范围操作时,可以使用NavigableMap。

TreeMap

官方介绍

一个基于红黑树的NavigableMap实现。根据键的自然顺序或在创建映射时提供的Comparator对映射进行排序,这取决于使用的是哪个构造函数。这个实现为containsKey、get、put和remove操作提供了保证的log(n)时间成本。算法改编自Cormen、Leiserson和Rivest的《算法导论》。

请注意,如果这个排序映射要正确实现map接口,那么树状映射所维护的排序(与任何排序映射一样)以及是否提供显式比较器都必须与equals一致。(参见Comparable或Comparator对consistent with equals的精确定义。)这是因为Map接口是根据equals操作定义的,但是排序映射使用它的compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,该方法认为相等的两个键是相等的。排序映射的行为是定义良好的,即使它的排序与等号不一致;它只是没有遵守Map接口的一般约定。

注意,这个实现是不同步的。如果多个线程并发地访问一个映射,并且至少有一个线程在结构上修改了映射,那么它必须在外部同步。(结构修改是添加或删除一个或多个映射的任何操作;仅仅改变与现有键相关联的值不是结构修改。)这通常是通过对一些自然封装映射的对象进行同步来完成的。

如果不存在这样的对象,则应该使用集合对映射进行“包装”。synchronizedSortedMap方法。这最好在创建时完成,以防止意外地对映射进行非同步访问:SortedMap m = Collections。synchronizedSortedMap(新TreeMap(…));这个类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间,以除通过迭代器自己的remove方法之外的任何方式修改映射,迭代器将抛出ConcurrentModificationException。

因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在未来不确定的时间冒任意的、不确定的行为的风险。

请注意,不能保证迭代器的快速故障行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败迭代器在尽最大努力的基础上抛出ConcurrentModificationException。因此,编写依赖于此异常的程序以确保其正确性是错误的:迭代器的快速失败行为应该仅用于检测错误。所有的地图。该类及其视图中的方法返回的条目对表示生成映射时的快照。他们不支持入盟。setValue方法。(但是请注意,可以使用put更改关联映射中的映射。)

简述

在Java中,TreeMap是SortedMap接口的实现类,它基于红黑树数据结构实现了有序映射。TreeMap根据键的自然顺序或自定义比较器对键值对进行排序,并保持键值对的有序性。

在这里插入图片描述
在这里插入图片描述

TreeMap的特点和使用方式如下:

  • 有序性:TreeMap保持键值对的有序性,可以根据键值的顺序进行范围查找、遍历和操作。
  • 自然顺序或自定义比较器:TreeMap可以很久键值的自然顺序(如果键实现了Comparable 接口) 或自定义比较器对键进行排序。
  • 快速查找: 用于使用红黑树作为底层数据结构,TreeMap具有快速查找性能,时间复杂度为O(log n)。
  • 提供子映射:TreeMap提供了subMap、headMap、tailMap等方法,可以获取原有映射的子映射,方便进行范围操作。
  • 不允许为null键: 由于TreeMap是基于键的有序性进行排序的,所以不允许使用null键,但允许使用null值。
import java.util.TreeMap;

public class TreeMapExample {
   public static void main(String[] args) {
       TreeMap<Integer, String> treeMap = new TreeMap<>();

       treeMap.put(3, "Apple");
       treeMap.put(1, "Banana");
       treeMap.put(2, "Orange");

       System.out.println(treeMap); // 输出:{1=Banana, 2=Orange, 3=Apple}

       System.out.println(treeMap.get(2)); // 输出:Orange

       treeMap.remove(1);
       System.out.println(treeMap); // 输出:{2=Orange, 3=Apple}
   }
}

在上面的示例中,我们创建了一个TreeMap对象,并向其中插入了三个键值对。由于TreeMap会根据键的自然顺序进行排序,因此输出的键值对按照键的顺序排列。

我们使用get方法获取键为2的值,成功输出"Orange"。然后,我们使用remove方法移除键为1的键值对,并输出剩余的键值对。

输出:

{1=Banana, 2=Orange, 3=Apple}
Orange
{2=Orange, 3=Apple}

通过使用TreeMap,我们可以方便地实现对键值对的有序操作,包括插入、查找、删除等。TreeMap的有序性和快速查找特性使得它在某些场景下比普通的HashMap更加适用。需要根据具体的需求权衡其优缺点,选择合适的数据结构。

TreeMap的优缺点和使用场景

优点:

  • 有序性:TreeMap保持键值对的有序性,可以根据键的顺序进行范围查找、遍历和操作。
  • 快速查找:由于使用红黑树作为底层数据结构,TreeMap具有快速的查找性能,时间复杂度为O(log n)。
  • 提供子映射:TreeMap提供了subMap、headMap和tailMap等方法,可以获取原有映射的子映射,方便进行范围操作。
  • 自然顺序或自定义比较器:TreeMap可以根据键的自然顺序(如果键实现了Comparable接口)或自定义比较器对键进行排序。

缺点

  • 内存占用:相比于普通的HashMap,TreeMap需要额外的内存来维护有序性,因此可能占用更多的内存空间。
  • 插入和删除性能略低:由于需要维护有序性,TreeMap在插入和删除元素时,相对于普通的HashMap会略微降低性能。

使用场景

  • 当需要对键值对进行有序操作时,可以使用TreeMap。
  • 当需要根据键的顺序进行范围查找、遍历和操作时,可以使用TreeMap。
  • 当需要获取最小/最大键值对或根据键的顺序进行导航操作时,可以使用TreeMap。
  • 当需要获取子映射进行范围操作时,可以使用TreeMap。

常用方法介绍

  • put(K key, V value):将指定的键值对插入到TreeMap中。
  • get(Object key):根据键获取对应的值。
  • remove(Object key):根据键移除对应的键值对。
  • containsKey(Object key):判断TreeMap中是否包含指定的键。
  • containsValue(Object value):判断TreeMap中是否包含指定的值。
  • size():返回TreeMap中键值对的数量。
  • isEmpty():判断TreeMap是否为空。
  • clear():清空TreeMap中的所有键值对。
  • firstKey():返回TreeMap中的最小键。
  • lastKey():返回TreeMap中的最大键。
  • lowerKey(K key):返回小于给定键的最大键,如果不存在则返回null。
  • floorKey(K key):返回小于等于给定键的最大键,如果不存在则返回null。
  • ceilingKey(K key):返回大于等于给定键的最小键,如果不存在则返回null。
  • higherKey(K key):返回大于给定键的最小键,如果不存在则返回null。
  • subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive):返回指定范围内的子映射。
  • headMap(K toKey, boolean inclusive):返回小于给定键的部分子映射。
  • tailMap(K fromKey, boolean inclusive):返回大于等于给定键的部分子映射。
  • descendingMap():返回一个与原有映射相反顺序的NavigableMap。
  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Miaow.Y.Hu

赏一口饭吃吧,大大们

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值