【问题标题】:Maintaining order in HashMap [duplicate]维护HashMap中的顺序[重复]
【发布时间】:2013-10-10 11:26:13
【问题描述】:

我有一个列表,我将其转换为地图来做一些工作。之后,我再次将地图转换回列表,但这次顺序是随机的。我需要在我的第二个列表中保留相同的初始订单。

明显的原因是 HashMap 不保持顺序。但我需要做一些事情才能做到这一点。我无法更改 Map 实现。我该怎么做?

考虑给定的代码:

import java.util.*;
public class Dummy {

public static void main(String[] args) {
    System.out.println("Hello world !");
    List<String> list = new ArrayList<String>();
    list.add("A");list.add("B");list.add("C");
    list.add("D");list.add("E");list.add("F");

    Map<String,String> map = new HashMap<String, String>();

    for(int i=0;i<list.size();i=i+2)
        map.put(list.get(i),list.get(i+1));

    // Use map here to do some work

    List<String> l= new ArrayList<String>();
    for (Map.Entry e : map.entrySet()) {
        l.add((String) e.getKey());
        l.add((String) e.getValue());
    }
  }
}

例如 - 最初,当我打印列表元素时,它会打印出来

A B C D E F 

现在,当我打印List l 的元素时,它打印出来了

E F A B C D

【问题讨论】:

标签: java


【解决方案1】:

HashMap 本身不维护插入顺序 - 但 LinkedHashMap 可以,因此请改用它。

据记录...HashMap:

这个类不保证地图的顺序;特别是,它不保证订单会随着时间的推移保持不变。

还有LinkedHashMap

Map 接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与 HashMap 的不同之处在于它维护一个双向链表,该列表贯穿其所有条目。该链表定义了迭代顺序,通常是键插入映射的顺序(插入顺序)。

【讨论】:

  • 先生,我无法更改地图的实现,因为它正在许多其他地方使用!没有别的办法吗?
  • @OneMoreError: 不。听起来不是你不能更改实现,而是你不想。 HashMap 非常清楚地记录了无法保证订单 - 如果您试图依赖它,那么您基本上有一个需要修复的错误。任务的大小不会影响它是否是您需要修复的错误。
  • 不能更改实现是没有意义的。在其他这些地方,他们是真的创建了一个HashMap,还是只取一个作为参数?您应该针对接口而不是实现进行编程。将它们更改为将 Map 作为参数而不是 HashMap,然后您可以随意替换实现。
【解决方案2】:

HashMap 不保留插入顺序

Map 接口的基于哈希表的实现。此实现提供所有可选的映射操作,并允许空值和空键。 (HashMap 类大致相当于 Hashtable,除了它是不同步的并且允许空值。)这个类不保证映射的顺序;特别是,它不保证订单会随着时间的推移保持不变。

如果您想保留键的顺序,请使用 LinkedHashMap

【讨论】:

    【解决方案3】:

    为什么不能更改 Map 实现(例如更改为 LinkedHashMap)?

    如果有逻辑排序,您可以使用自定义Comparator 对列表进行排序。

    【讨论】:

      【解决方案4】:

      使用 LinkedHashMap 代替 HashMap 来维护秩序。

      Map<String,String> map = new LinkedHashMap<String, String>();
      

      【讨论】:

      • s/LinkedHasMap/LinkedHashMap/
      【解决方案5】:

      考虑让您的物品可分类。在字符串的情况下,已经存在自然排序;按字母顺序排列。您可以制作使用 sortable 类的对象,因此您可以使用排序算法将这些对象按良好的顺序排列,无论您从哈希中获取它们的顺序是什么!

      【讨论】:

        【解决方案6】:

        现在是LinkedHashMap 的时间了,它的目的就是为了保留插入顺序。

        请注意,即使是 TreeMap 也存在,它允许您通过使用 Comparable 界面来保持所需的顺序。它不再是哈希映射,而是一棵树。

        【讨论】:

          【解决方案7】:

          如果您确实无法切换到另一个 Map 实现 (LinkedHashMap 正是您想要的),那么唯一的另一种可能性是保留原来的 List, 并将其用于从Map. 创建新的List

          public <T> List<T> listFromMapInOrder(final Map<T, T> map, final List<T> order) {
              List<T> result = new ArrayList<T>();
              for (T key : order) {
                  if (map.containsKey(key)) {
                      result.add(key);
                      result.add(map.get(key));
                  }
              }
              return result;
          }
          

          但我会重构代码,直到可以切换到LinkedHashMap.

          【讨论】:

            猜你喜欢
            • 2015-09-12
            • 2018-06-16
            • 2020-01-06
            • 2013-08-08
            • 2011-02-27
            • 2017-10-12
            • 2016-06-05
            • 2015-04-28
            • 1970-01-01
            相关资源
            最近更新 更多