如何在不更改值顺序的情况下反转 TreeMap 的键顺序?

How to reverse the order of keys of a TreeMap without changing the order of the values?

我有一个 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 的一些公共集合实用程序,但没有立即看到任何可以解决问题的东西。

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

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

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

在这种情况下,如果Key-Value和loosely related,我们能想到把这个放在两个不同的List中吗?根据需要在需要时重新映射。

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

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

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

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

颠倒地图中键的顺序与创建新地图相同。为此,首先创建一个包含当前地图条目的列表,然后同时在两个方向上迭代该列表,并将 collect a new map. This is enough for LinkedHashMap, and for TreeMap you have to additionally specify a 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?