【问题标题】:How to reverse the order of keys of a TreeMap without changing the order of the values?如何在不更改值顺序的情况下反转 TreeMap 的键顺序?
【发布时间】:2021-05-12 19:08:16
【问题描述】:

我有一个像这样的TreeMap

{
    "one": "First option",
    "two": "Second option",
    "three": "Third option",
    "four": "Last option"
}

我想使用这个对象,以便输出如下:

{
    "four": "First option",
    "three": "Second option",
    "two": "Third option",
    "one": "Last option"
}

我正在查看一些来自 apache 的公共集合实用程序,但没有立即看到任何可以解决问题的方法。

没有一堆循环的最简洁的方法是什么?

【问题讨论】:

    标签: java sorting dictionary hashmap treemap


    【解决方案1】:

    我认为你只能使用 LinkedHashMap 来存储这样的列表,因为它不是按字母顺序排列的。但是 LinkedHashMap 保持元素添加的顺序,这样就可以了。

    我认为没有什么比将所有映射条目(可通过entrySet() 方法获得)放入 ArrayList 中,然后通过遍历此数组以相反的顺序将它们添加到另一个映射中更简单的方法了。如果它是反向迭代器,我们可以派生一个交换它们的类,但看起来没有迭代器会以相反的顺序移动,所以重写不是一种选择。

    在创建地图后更改键的哈希码不会改变顺序,因为桶已经在那里。但是,它可能会阻止地图正常工作。

    【讨论】:

      【解决方案2】:

      这意味着你的映射函数(首先是如何生成 Map)是错误的。

      无论您使用哪种Map 实现,保存键值对都是合适的数据结构。通过反转/打乱具有不同值的键来扭曲键值对来违背此数据结构的基本原则是没有意义的。

      在这种情况下,如果Key-Value和松散相关,我们可以考虑把这个放在两个不同的List中吗?根据需要在需要时重新映射它。

      此外,three 将在您的 TreeMap 中放置在 two 之前。不就是这样组织的吗*?

      【讨论】:

        【解决方案3】:

        反转映射中键的顺序与创建新映射相同。为此,首先创建一个包含当前地图条目的列表,然后一次在两个方向上迭代该列表并collect 一个新地图。这对于LinkedHashMap 来说已经足够了,对于TreeMap,您必须另外指定一个reversed 比较器到之前的比较器。示例:

        1. TreeMap

          TreeMap<Integer, String> map1 =
                  new TreeMap<>(Comparator.naturalOrder()) {{
                      put(1, "First option");
                      put(2, "Second option");
                      put(3, "Third option");
                      put(4, "Last option");
                  }};
          
          List<Map.Entry<Integer, String>> list1 = new ArrayList<>(map1.entrySet());
          
          TreeMap<Integer, String> map2 = IntStream.range(0, list1.size())
                  .boxed().collect(Collectors.toMap(
                          // from the end to the beginning
                          i -> list1.get(list1.size() - i - 1).getKey(),
                          // from the beginning to the end
                          i -> list1.get(i).getValue(),
                          // merge duplicates, if any
                          (s1, s2) -> s1 + "," + s2,
                          // reversed comparator to the one that was before
                          () -> new TreeMap<>(map1.comparator().reversed())));
          
          // output
          map2.forEach((k, v) -> System.out.println(k + " : " + v));
          //4 : First option
          //3 : Second option
          //2 : Third option
          //1 : Last option
          

        2. LinkedHashMap

          LinkedHashMap<String, String> map3 =
                  new LinkedHashMap<>() {{
                      put("one", "First option");
                      put("two", "Second option");
                      put("three", "Third option");
                      put("four", "Last option");
                  }};
          
          List<Map.Entry<String, String>> list2 = new ArrayList<>(map3.entrySet());
          
          LinkedHashMap<String, String> map4 = IntStream.range(0, list2.size())
                  .boxed().collect(Collectors.toMap(
                          // from the end to the beginning
                          i -> list2.get(list2.size() - i - 1).getKey(),
                          // from the beginning to the end
                          i -> list2.get(i).getValue(),
                          // merge duplicates, if any
                          (s1, s2) -> s1 + "," + s2,
                          LinkedHashMap::new));
          
          // output
          map4.forEach((k, v) -> System.out.println(k + " : " + v));
          //four : First option
          //three : Second option
          //two : Third option
          //one : Last option
          

        另见:How do I sort two arrays in relation to each other?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-14
          • 1970-01-01
          • 2011-01-23
          • 1970-01-01
          相关资源
          最近更新 更多