我有这张地图:
Map < String, String > unsortMap = new HashMap < String, String > ();
unsortMap.put("./cq:dialog/content/items/tabs/items/tab1/items/columns/items", "40");
unsortMap.put("./cq:dialog/content", "80");
unsortMap.put("./cq:dialog", "75");
unsortMap.put("./cq:dialog/content/items/tabs/items/tab2/items/columns/items", "40");
unsortMap.put("./cq:dialog/content/sling:resourcetype", "granite/ui/components/coral/foundation/container");
我想根据键的长度对它进行排序,例如,如果键的“ /”数量较少,那么它将排在最前面。
预期输出:
./cq:dialog
./cq:dialog/content/
./cq:dialog/content/sling:resourcetype
./cq:dialog/content/items/tabs/items/tab1/items/columns/items
./cq:dialog/content/items/tabs/items/tab2/items/columns/items
为此,我这样写:
Map<String, String> sortedMap = unsortMap.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
由于未根据“ /”进行比较,因此未提供预期的输出。我已经尝试过自定义比较器,但无法获得预期的结果。
答案 0 :(得分:3)
仅比较长度,我们可以在自定义比较器中使用Integer.compare
。 Demo
Map<String, String> sortedMap = unsortMap.entrySet().stream()
.sorted((a, b) -> Integer.compare(a.getKey().length(), b.getKey().length()))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new));
当然,您也可以使用此自定义比较器创建一个TreeMap
,以便仍然可以正确订购新密钥。
final NavigableMap<String, String> sortedMap = new TreeMap<>(
(a, b) -> a.length() != b.length() ? Integer.compare(a.length(), b.length()) : a.compareTo(b));
sortedMap.putAll(unsortMap);
为了比较斜杠的数量,我们可以过滤两个字符串的字符。
final NavigableMap<String, String> sortedMap = new TreeMap<>((a, b) -> {
final long slashes1 = a.chars().filter(c -> c == '/').count();
final long slashes2 = b.chars().filter(c -> c == '/').count();
return slashes1 != slashes2 ? Long.compare(slashes1, slashes2) : a.compareTo(b);
});
sortedMap.putAll(unsortMap);
如Andreas所建议,可以使用.thenComparing
简化比较器:
final NavigableMap<String, String> sortedMap = new TreeMap<>(
Comparator.comparingLong((String s) -> s.chars().filter(c -> c == '/').count())
.thenComparing(Comparator.naturalOrder()));
或者:
Map<String, String> sortedMap = unsortMap.entrySet().stream()
.sorted((a, b) -> Long.compare(a.getKey().chars().filter(c->c=='/').count(), b.getKey().chars().filter(c->c=='/').count()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
LinkedHashMap::new));