使用流按 List<String> 排序 Map<String, Integer>
Ordering Map<String, Integer> by List<String> using streams
Map<String, Integer> nonOrderedData = // {b=1, c=2, d=3, e=4, a=0}
List<String> orderSequence = // a, b, c, d, e
我需要应用排序序列来获取正确排序的数据,我如何使用(首选)流实现此目的?
我用的是非流方式:
Map<String, Integer> orderedData = new HashMap<>();
for (Map.Entry<String, Integer> nod : nonOrderedData.entrySet()) {
for (String os : orderSequence) {
if (os == nod.getKey()) {
// add nonOrderedData data
} else {
// add data by sequence
}
}
}
想要用更简洁的方式来实现我想要的东西。
我注意到在我的方法中我可以只 return new TreeMap<>(nonOrderedData)
它会工作得很好,但我不想坚持只应用 asc 顺序 - 我想读取实际序列值,然后更改 nonOrderedData
.
HashMap
不能用来存储orderedData
,因为它不保证其键的顺序,所以应该使用LinkedHashMap
来维护插入顺序。
使用流按 orderSequence
中显示的数据排序可以通过两种模式实现:
- 仅保留
nonOrderedData
: 中可用的值
Map<String, Integer> nonOrderedData = Map.of(
"b", 1, "e", 4, "a", 0, "o", 5, "d", 7
);
List<String> orderSequence = Arrays.asList(
"a", "e", "i", "o", "u", "b", "c", "d"
);
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::get,
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reordered);
输出:
{a=0, e=4, o=5, b=1, d=7}
在orderSequence
和nonOrderedData
之间类似于INNER JOIN
。
- 如果
orderSequence
中的密钥在 nonOrderedData
中丢失,则用一些默认值填充 reorderedData
:
Map<String, Integer> reorderedWithDefault = orderSequence
.stream()
.collect(Collectors.toMap(
key -> key, nonOrderedData.getOrDefault(key, -1),
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reorderedWithDefault);
输出:
{a=0, e=4, i=-1, o=5, u=-1, b=1, c=-1, d=7}
在orderSequence
和nonOrderedData
之间类似于LEFT JOIN
。
更新
在上述实现中,nonOrderedData
中与 orderSequence
中的键不匹配的键值对被完全跳过。可以使用 Map::remove (Object key)
跟踪此类键(并稍后添加到 reordered
结果),其中 returns 键的值被删除。
然而,下面的两个代码示例在流执行之外修改了nonOrderedData
的状态。
- 只保留来自
nonOrderedData
的键和相关值,将不匹配的对放在最后:
Map<String, Integer> nonOrderedData = new HashMap<>(Map.of(
"b", 1, "e", 4, "z", 8, "a", 0, "q", 6,
"f", 5, "d", 7
));
List<String> orderSequence = Arrays.asList("a", "e", "i", "o", "u", "b", "c", "d");
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainder = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainder);
reordered.putAll(remainder);
System.out.println(reordered);
输出:
remained: {f=5, q=6, z=8}
{a=0, e=4, b=1, d=7, f=5, q=6, z=8}
在orderSequence
和nonOrderedData
之间类似于RIGHT JOIN
。
- 保持
orderSequence
和 nonOrderedData
的所有值类似于 FULL JOIN
此处将为 orderSequence
中的非映射键提供默认值,并将 nonOrderedData
中的非匹配键添加到末尾。
Map<String, Integer> reorderedFull = orderSequence
.stream()
.peek(key -> nonOrderedData.computeIfAbsent(key, (k) -> -1)) // default value
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainderFull = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainderFull);
reorderedFull.putAll(remainderFull);
System.out.println(reorderedFull);
输出:
remained: {f=5, q=6, z=8}
{a=0, e=4, i=-1, o=-1, u=-1, b=1, c=-1, d=7, f=5, q=6, z=8}
如果您有一个有序序列,您可以从该序列收集一个包含键和值的新映射 从 无序映射 使用 remove
方法, 从该映射中删除键 的映射和 returns 前一个值.
收集新地图后,如果无序地图中还有剩余内容,您可以使用putAll
方法添加这些条目。
Map<String, Integer> nonOrderedData = new HashMap<>(
Map.of("f", 5, "b", 1, "c", 2, "d", 3, "e", 4, "a", 0));
List<String> orderSequence = List.of("a", "b", "c", "d", "e");
Map<String, Integer> orderedMap = orderSequence.stream()
.collect(LinkedHashMap::new,
(col, e) -> col.put(e, nonOrderedData.remove(e)),
HashMap::putAll);
System.out.println(orderedMap); // {a=0, b=1, c=2, d=3, e=4}
System.out.println(nonOrderedData); // {f=5}
orderedMap.putAll(nonOrderedData); // add what's left
System.out.println(orderedMap); // {a=0, b=1, c=2, d=3, e=4, f=5}
同样,您可以收集地图条目列表:
,而不是地图
Map<String, Integer> nonOrderedData = new HashMap<>(
Map.of("f", 5, "b", 1, "c", 2, "d", 3, "e", 4, "a", 0));
List<String> orderSequence = List.of("a", "b", "c", "d", "e");
List<Map.Entry<String, Integer>> orderedList = orderSequence.stream()
.map(e -> Map.entry(e, nonOrderedData.remove(e)))
.collect(Collectors.toList());
System.out.println(orderedList); // [a=0, b=1, c=2, d=3, e=4]
System.out.println(nonOrderedData); // {f=5}
orderedList.addAll(nonOrderedData.entrySet()); // add what's left
System.out.println(orderedList); // [a=0, b=1, c=2, d=3, e=4, f=5]
Map<String, Integer> nonOrderedData = // {b=1, c=2, d=3, e=4, a=0}
List<String> orderSequence = // a, b, c, d, e
我需要应用排序序列来获取正确排序的数据,我如何使用(首选)流实现此目的?
我用的是非流方式:
Map<String, Integer> orderedData = new HashMap<>();
for (Map.Entry<String, Integer> nod : nonOrderedData.entrySet()) {
for (String os : orderSequence) {
if (os == nod.getKey()) {
// add nonOrderedData data
} else {
// add data by sequence
}
}
}
想要用更简洁的方式来实现我想要的东西。
我注意到在我的方法中我可以只 return new TreeMap<>(nonOrderedData)
它会工作得很好,但我不想坚持只应用 asc 顺序 - 我想读取实际序列值,然后更改 nonOrderedData
.
HashMap
不能用来存储orderedData
,因为它不保证其键的顺序,所以应该使用LinkedHashMap
来维护插入顺序。
使用流按 orderSequence
中显示的数据排序可以通过两种模式实现:
- 仅保留
nonOrderedData
: 中可用的值
Map<String, Integer> nonOrderedData = Map.of(
"b", 1, "e", 4, "a", 0, "o", 5, "d", 7
);
List<String> orderSequence = Arrays.asList(
"a", "e", "i", "o", "u", "b", "c", "d"
);
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::get,
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reordered);
输出:
{a=0, e=4, o=5, b=1, d=7}
在orderSequence
和nonOrderedData
之间类似于INNER JOIN
。
- 如果
orderSequence
中的密钥在nonOrderedData
中丢失,则用一些默认值填充reorderedData
:
Map<String, Integer> reorderedWithDefault = orderSequence
.stream()
.collect(Collectors.toMap(
key -> key, nonOrderedData.getOrDefault(key, -1),
(v1, v2) -> v1, LinkedHashMap::new
));
System.out.println(reorderedWithDefault);
输出:
{a=0, e=4, i=-1, o=5, u=-1, b=1, c=-1, d=7}
在orderSequence
和nonOrderedData
之间类似于LEFT JOIN
。
更新
在上述实现中,nonOrderedData
中与 orderSequence
中的键不匹配的键值对被完全跳过。可以使用 Map::remove (Object key)
跟踪此类键(并稍后添加到 reordered
结果),其中 returns 键的值被删除。
然而,下面的两个代码示例在流执行之外修改了nonOrderedData
的状态。
- 只保留来自
nonOrderedData
的键和相关值,将不匹配的对放在最后:
Map<String, Integer> nonOrderedData = new HashMap<>(Map.of(
"b", 1, "e", 4, "z", 8, "a", 0, "q", 6,
"f", 5, "d", 7
));
List<String> orderSequence = Arrays.asList("a", "e", "i", "o", "u", "b", "c", "d");
Map<String, Integer> reordered = orderSequence
.stream()
.filter(nonOrderedData::containsKey)
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainder = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainder);
reordered.putAll(remainder);
System.out.println(reordered);
输出:
remained: {f=5, q=6, z=8}
{a=0, e=4, b=1, d=7, f=5, q=6, z=8}
在orderSequence
和nonOrderedData
之间类似于RIGHT JOIN
。
- 保持
orderSequence
和nonOrderedData
的所有值类似于FULL JOIN
此处将为 orderSequence
中的非映射键提供默认值,并将 nonOrderedData
中的非匹配键添加到末尾。
Map<String, Integer> reorderedFull = orderSequence
.stream()
.peek(key -> nonOrderedData.computeIfAbsent(key, (k) -> -1)) // default value
.collect(Collectors.toMap(
key -> key, nonOrderedData::remove,
(v1, v2) -> v1, LinkedHashMap::new
));
SortedMap<String, Integer> remainderFull = new TreeMap<>(nonOrderedData);
System.out.println("remained: " + remainderFull);
reorderedFull.putAll(remainderFull);
System.out.println(reorderedFull);
输出:
remained: {f=5, q=6, z=8}
{a=0, e=4, i=-1, o=-1, u=-1, b=1, c=-1, d=7, f=5, q=6, z=8}
如果您有一个有序序列,您可以从该序列收集一个包含键和值的新映射 从 无序映射 使用 remove
方法, 从该映射中删除键 的映射和 returns 前一个值.
收集新地图后,如果无序地图中还有剩余内容,您可以使用putAll
方法添加这些条目。
Map<String, Integer> nonOrderedData = new HashMap<>(
Map.of("f", 5, "b", 1, "c", 2, "d", 3, "e", 4, "a", 0));
List<String> orderSequence = List.of("a", "b", "c", "d", "e");
Map<String, Integer> orderedMap = orderSequence.stream()
.collect(LinkedHashMap::new,
(col, e) -> col.put(e, nonOrderedData.remove(e)),
HashMap::putAll);
System.out.println(orderedMap); // {a=0, b=1, c=2, d=3, e=4}
System.out.println(nonOrderedData); // {f=5}
orderedMap.putAll(nonOrderedData); // add what's left
System.out.println(orderedMap); // {a=0, b=1, c=2, d=3, e=4, f=5}
同样,您可以收集地图条目列表:
,而不是地图Map<String, Integer> nonOrderedData = new HashMap<>(
Map.of("f", 5, "b", 1, "c", 2, "d", 3, "e", 4, "a", 0));
List<String> orderSequence = List.of("a", "b", "c", "d", "e");
List<Map.Entry<String, Integer>> orderedList = orderSequence.stream()
.map(e -> Map.entry(e, nonOrderedData.remove(e)))
.collect(Collectors.toList());
System.out.println(orderedList); // [a=0, b=1, c=2, d=3, e=4]
System.out.println(nonOrderedData); // {f=5}
orderedList.addAll(nonOrderedData.entrySet()); // add what's left
System.out.println(orderedList); // [a=0, b=1, c=2, d=3, e=4, f=5]