[英]Java8 Stream grouping by with toMap issue
我有一个名为 ConfigKey 的ConfigKey
public class ConfigKey {
String code;
String key;
String value;
//omit setter and getter
}
我想将List<ConfigKey>
转换为Map<String, Map<String, Object>>
,这是我的方法定义
public Map<String, Map<String, Object> convert (List<ConfigKey> list) {
return list.stream().collect(Collectors.groupingBy(ConfigKey::getCode,
Collectors.toMap(ConfigKey::getKey, ConfigKey::getValue)));
}
但是我想做一些更改,为每个ConfigKey
将另一个密钥放入 map,例如
{ "code": "code1","key", "key1", "value": "value1"}
to Map
{"code1": {"key1":"value1", "prefix_key1": "value1" }
有没有 API 像下面这样:
public Map<String, Map<String, Object> convert (List<ConfigKey> list) {
return list.stream().collect(Collectors.groupingBy(ConfigKey::getCode,
Collectors.toMap("prefix_" + ConfigKey::getKey, ConfigKey::getValue))
Collectors.toMap(ConfigKey::getKey, ConfigKey::getValue)));
}
您可以使用Collector.of()
工厂方法,它允许您创建自己的收集器:
public Map<String, Map<String, Object> convert (List<ConfigKey> list) {
return list.stream().collect(Collectors.groupingBy(ConfigKey::getCode, Collector.of(
HashMap::new, (m, c) -> {
m.put(c.getKey(), c.getValue());
m.put("prefix_" + c.getKey(), c.getValue());
}, (a, b) -> {
a.putAll(b);
return b;
}
)));
}
但老实说,这似乎有点混乱,也许一个正常的循环会更好。 流的目的是提供一个 api ,它以更易读的方式做事,但是当你不得不修改这个结构时,通过引入一些非常不可读的逻辑,那么几乎总是更好的选择,只是用旧的方式来做:
public Map<String, Map<String, Object> convert (List<ConfigKey> list) {
Map<String, Map<String, Object>> map = new HashMap<>();
for (ConfigKey ck : list) {
Map<String, Object> inner = map.computeIfAbsent(ck.getCode(), k -> new HashMap<>());
inner.put(ck.getKey(), ck.getValue());
inner.put("prefix_" + ck.getKey(), ck.getValue());
}
return map;
}
您可以先将新条目添加到 map,然后将它们分组:
private Map<String, Map<String, Object>> convert(List<ConfigKey> list) {
new ArrayList<>(list).stream().map(configKey -> new ConfigKey(configKey.getCode(), "prefix_" + configKey.getKey(), configKey.getValue())).forEachOrdered(list::add);
return list.stream().collect(Collectors.groupingBy(ConfigKey::getCode,
Collectors.toMap(ConfigKey::getKey, ConfigKey::getValue)));
}
我克隆了列表(为了防止 ConcurrentModificationException),然后将键更改为“新”键(带有映射)并将它们添加到原始列表 - forEachOrdered(list::add)。 由于“代码”字段未更改,因此两个条目都将使用它,从而导致 map 中有 2 个条目
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.