根据另一个地图中的值对 Java 个地图进行排序
Sort Java Map based on values in another map
作为输入,我有对象列表,每个对象都有名称和映射:
1)
Name: m1
Map: {"c1": 3,
"c2": 24
"c3": 12}
2) Name: m2
Map: {"c1": "A",
"c2": "B",
"c3": "C"}
3) Name: m3
Map: {"c1": 3.4,
"c2": 4.6,
"c3": 12.3}
我需要的输出是,我需要根据名称为 m1.
的地图中的值对所有 3 个地图进行排序
所以首先,我想对对象#1(m1) 按值降序排序映射(我可以使用 LinedHashMap这里):
{"c1": 3, "c2": 24, "c3": 12} => {"c2": 24, "c3": 12, "c1": 3}
现在,我希望对象#2 的映射和对象#3 的映射中的元素也按相同的键顺序排序 - C2、C3、C1。所以基本上我想重新排序 2 张地图,以便顺序为 C2、C3、C1(与 m1 中的顺序相同),以及 NOT C1、C2 , C3.
我怎样才能以最优雅的方式做到这一点?我有一些解决方案 - 但它们很混乱,并且有很多额外的步骤。
重要的是:此列表始终只有 3 个对象。地图中的元素数量可以不同,但地图中的键在 3 个地图中始终相同
所以你知道如何按值对 Map
进行排序,也许通过阅读这个答案:Sort a Map by values (Java),其中 Java 8 版本的答案是:
m1sorted = m1.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Collections.reverseOrder()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
那么如何根据 m1
的值对 m2
和 m3
进行排序?
简单:您提供 Comparator
到 sorted()
来比较值,例如
.sorted(Comparator.comparing(e -> m1.get(e.getKey())).reversed())
您可能必须明确指定 e
的类型,因为推理引擎可能会丢失:comparing((Entry<String, String> e) ->
如果您不喜欢 Comparator.comparing()
和 reversed()
,以及推理问题,您可以使用 lambda。
这是所有代码,作为概念证明:
Map<String, Integer> m1 = new HashMap<>();
m1.put("c1", 3);
m1.put("c2", 24);
m1.put("c3", 12);
Map<String, String> m2 = new HashMap<>();
m2.put("c1", "A");
m2.put("c2", "B");
m2.put("c3", "C");
Map<String, Double> m3 = new HashMap<>();
m3.put("c1", 3.4);
m3.put("c2", 4.6);
m3.put("c3", 12.3);
Map<String, Integer> m1s =
m1.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
Map<String, String> m2s =
m2.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(m1.get(e2.getKey()), m1.get(e1.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
Map<String, Double> m3s =
m3.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(m1.get(e2.getKey()), m1.get(e1.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
System.out.println(m1s);
System.out.println(m2s);
System.out.println(m3s);
输出
{c2=24, c3=12, c1=3}
{c2=B, c3=C, c1=A}
{c2=4.6, c3=12.3, c1=3.4}
注意 e2
和 e1
如何在 lambda 中颠倒以导致降序。
当然,使用Java的Object-Oriented特性就更好了,只有一个Map
到三个字段的对象对于值。
作为输入,我有对象列表,每个对象都有名称和映射:
1)
Name: m1
Map: {"c1": 3,
"c2": 24
"c3": 12}
2) Name: m2
Map: {"c1": "A",
"c2": "B",
"c3": "C"}
3) Name: m3
Map: {"c1": 3.4,
"c2": 4.6,
"c3": 12.3}
我需要的输出是,我需要根据名称为 m1.
的地图中的值对所有 3 个地图进行排序所以首先,我想对对象#1(m1) 按值降序排序映射(我可以使用 LinedHashMap这里):
{"c1": 3, "c2": 24, "c3": 12} => {"c2": 24, "c3": 12, "c1": 3}
现在,我希望对象#2 的映射和对象#3 的映射中的元素也按相同的键顺序排序 - C2、C3、C1。所以基本上我想重新排序 2 张地图,以便顺序为 C2、C3、C1(与 m1 中的顺序相同),以及 NOT C1、C2 , C3.
我怎样才能以最优雅的方式做到这一点?我有一些解决方案 - 但它们很混乱,并且有很多额外的步骤。
重要的是:此列表始终只有 3 个对象。地图中的元素数量可以不同,但地图中的键在 3 个地图中始终相同
所以你知道如何按值对 Map
进行排序,也许通过阅读这个答案:Sort a Map by values (Java),其中 Java 8 版本的答案是:
m1sorted = m1.entrySet() .stream() .sorted(Map.Entry.comparingByValue(Collections.reverseOrder())) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new ));
那么如何根据 m1
的值对 m2
和 m3
进行排序?
简单:您提供 Comparator
到 sorted()
来比较值,例如
.sorted(Comparator.comparing(e -> m1.get(e.getKey())).reversed())
您可能必须明确指定 e
的类型,因为推理引擎可能会丢失:comparing((Entry<String, String> e) ->
如果您不喜欢 Comparator.comparing()
和 reversed()
,以及推理问题,您可以使用 lambda。
这是所有代码,作为概念证明:
Map<String, Integer> m1 = new HashMap<>();
m1.put("c1", 3);
m1.put("c2", 24);
m1.put("c3", 12);
Map<String, String> m2 = new HashMap<>();
m2.put("c1", "A");
m2.put("c2", "B");
m2.put("c3", "C");
Map<String, Double> m3 = new HashMap<>();
m3.put("c1", 3.4);
m3.put("c2", 4.6);
m3.put("c3", 12.3);
Map<String, Integer> m1s =
m1.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
Map<String, String> m2s =
m2.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(m1.get(e2.getKey()), m1.get(e1.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
Map<String, Double> m3s =
m3.entrySet()
.stream()
.sorted((e1, e2) -> Integer.compare(m1.get(e2.getKey()), m1.get(e1.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new));
System.out.println(m1s);
System.out.println(m2s);
System.out.println(m3s);
输出
{c2=24, c3=12, c1=3}
{c2=B, c3=C, c1=A}
{c2=4.6, c3=12.3, c1=3.4}
注意 e2
和 e1
如何在 lambda 中颠倒以导致降序。
当然,使用Java的Object-Oriented特性就更好了,只有一个Map
到三个字段的对象对于值。