有序的Map集合

部署运行你感兴趣的模型镜像

  我们通常使用的Map集合是HashMap,在大多数情况下HashMap可以满足我们的要求,但是HashMap有一个缺点:HashMap是无序的,即其迭代顺序与其key或value的大小无关。而在某些情况下,如果我们需要Map集合里的元素有序,那么HashMap是不能满足我们的要求的。

那么有没有有序的Map集合呢?有,Java提供了两种有序的Map集合:LinkedHashMapTreeMap

(一)LinkedHashMap

LinkedHashMap继承了HashMap,是HashMap的子类。

其实LinkedHashMap与HashMap区别不大,也是通过计算键的hash值,映射到hash表中,那么LinkedHashMap是如何实现有序的呢?

LinkedHashMap不仅维护着一个hash表,而且还维护着一个双向链表,而这个双向链表里的元素就是有序的。

LinkedHashMap的Entry继承于HashMap的Entry,并且增加了before和after属性。

 

可以看到before和after的类型都是Entry,LinkedHashMap通过before和after来构建双向链表。

LinkedHashMap的内部结构如图所示:

 

LinkedHashMap有两种排序方式:插入排序和访问排序(修改或访问一个元素后,将该元素移到队列末尾),默认是插入排序。使用accessOrder来标记使用哪种排序方式,accessOrder==true时,表示使用访问排序默认为false;注意:LinkedHashMap的有序不是keyvalue的自然顺序

LinkedHashMap的插入:

put():

LinkedHashMap的put方法和HashMap的相同,不过LinkedHashMap重写了newNode方法,在插入时,会判断双向链表是否为空,如果为空,则将该Entry作为头结点head,否则在双向链表末尾插入该Entry;如果更新值(key相同),则会判断accessOrder是否为true,如果为true,则将该Entry移到双向队列的尾部。

get():

LinkedHashMap在get的时候,会判断accessOrder是否为true,即是否按访问顺序排序,如果是true,则会把该Entry移到双向队列的尾部。然后再返回value。

LinkedHashMap的迭代:

LinkedHashMapIterator实现了迭代器的功能,其是对双向循环链表的遍历操作。但是这个迭代器是abstract的,不能直接被对象所用。

LinkedHashMap中的LinkedKeyIteratorLinkedValueIteratorLinkedEntryIterator都继承了LinkedHashMapIterator,并且实现了Iterator接口,我们可以使用上面三种迭代器来迭代keyvalueentry三种迭代器迭代的是同一个双向链表,即迭代的元素是相同的,只是返回的类型不同。

 

遍历TreeMap的键值对

LinkedHashMap map = new LinkedHashMap();
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
    Map.Entry entry = (Map.Entry)iter.next();
    // 获取key
    key = (String)entry.getKey();
        // 获取value
    integ = (Integer)entry.getValue();
}

(二)TreeMap

TreeMap也是一个有序的Map集合,其底层是一颗红黑树,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

TreeMap的Entry结构如下:

可以看出来TreeMap的Entry其实是一个树节点,构建了一颗红黑树。而entry的插入,就是在红黑树中新增一个节点,并调整红黑树。

TreeMap的插入:

put():

如果Comparator 为空,会使用key进行比较,按照从小到大的次序插入到红黑树中。

如果Comparator 不为空,则根据Comparator来进行比较。

TreeMap的迭代:

PrivateEntryIterator实现了迭代器的功能,其是对红黑树进行遍历,返回的是红黑树中的有序序列。但是这个迭代器是abstract的,不能直接被对象所用。迭代时使用的是EntryIterator,ValueIterator,KeyIterator等迭代器。

除了顺序遍历,TreeMap还可以逆序遍历,由于TreeMap中的元素是从小到大的顺序排列的。因此,顺序遍历,就是从第一个元素开始,逐个向后遍历;而倒序遍历则恰恰相反,它是从最后一个元素开始,逐个往前遍历。

 

遍历TreeMap的键值对

TreeMap map = new TreeMap ();
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
    Map.Entry entry = (Map.Entry)iter.next();
    // 获取key
    key = (String)entry.getKey();
        // 获取value
    integ = (Integer)entry.getValue();
}

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

在 Java 中,若需要获取一个有序的 `Map` 集合,通常可以选择以下几种方式实现: ### 1. 使用 `LinkedHashMap` `LinkedHashMap` 是 `HashMap` 的子类,它通过维护插入顺序或访问顺序来实现有序性。默认情况下,它会按照键值对的插入顺序进行排序。 ```java import java.util.*; public class Main { public static void main(String[] args) { Map<String, Integer> map = new LinkedHashMap<>(); map.put("one", 1); map.put("two", 2); map.put("three", 3); // 按照插入顺序输出 for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } ``` 如果希望按照访问顺序排列,可以在构造 `LinkedHashMap` 时提供适当的参数: ```java Map<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true); ``` 在这种模式下,最近访问的元素会被移动到末尾。 ### 2. 使用 `TreeMap` `TreeMap` 是基于红黑树实现的 `Map`,它会根据键的自然顺序或者自定义比较器对键进行排序。 ```java import java.util.*; public class Main { public static void main(String[] args) { Map<String, Integer> map = new TreeMap<>(); map.put("three", 3); map.put("one", 1); map.put("two", 2); // 按照键的自然顺序输出 for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } ``` 如果键是自定义对象,则需要确保该类实现了 `Comparable` 接口,或者为 `TreeMap` 提供一个自定义的 `Comparator`。 ### 3. 对现有 `Map` 进行排序 如果已经有了一个无序的 `Map`,并且希望将其按键或值排序后存储在一个有序集合中,可以使用如下方法: #### 按键排序 ```java import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> unsortedMap = new HashMap<>(); unsortedMap.put("three", 3); unsortedMap.put("one", 1); unsortedMap.put("two", 2); // 按键排序并存入新的 TreeMap Map<String, Integer> sortedMap = new TreeMap<>(unsortedMap); // 输出排序后的 Map for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } ``` #### 按值排序 ```java import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { Map<String, Integer> unsortedMap = new HashMap<>(); unsortedMap.put("three", 3); unsortedMap.put("one", 1); unsortedMap.put("two", 2); // 按值排序并存入新的 LinkedHashMap(保持顺序) Map<String, Integer> sortedMap = unsortedMap.entrySet() .stream() .sorted(Map.Entry.comparingByValue()) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new )); // 输出排序后的 Map for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) { System.out.println(entry.getKey() + ": " + entry.getValue()); } } } ``` ### 总结 - 如果希望保持插入顺序,选择 `LinkedHashMap`。 - 如果希望按键的自然顺序或自定义顺序排序,选择 `TreeMap`。 - 如果已有无序 `Map`,可以通过流操作将其排序后存入有序集合中。 这些方法均能有效地帮助开发者实现从 `Map` 获取有序集合的需求。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值