所以,我有这个函数,它接受一个映射,其中一个名称与一个不同的索引之一相关联到一个数组中。索引号只会有一个与之关联的名称,因此没有重复项和空值,因此使用以下函数可以安全地展平层次结构。
public Map<Integer, Object> normalize( Map<Object, List<Integer>> hierarchalMap ) {
Map<Integer, Object> normalizedMap = new HashMap<>();
for (Map.Entry<Object, List<Integer>> entry : hierarchalMap.entrySet()) {
for (Integer integer : entry.getValue()) {
noramizedMap.put(integer, entry.getKey());
}
}
return normalizedMap;
}
我试图将此功能更改为使用流API,而且我已经做到了这一点:
Map<Integer, Object> noramizedMap = new HashMap<>();
for (Map.Entry<Object, List<Integer>> entry : vars.entrySet()) {
entry.getValue().forEach(e -> noramizedMap.put(e, entry.getValue()));
}
如果这是一些其他功能语言,我会做部分绑定或其他什么但是用java我尝试将外部循环解包到流中...收集我只是迷路了。
答案 0 :(得分:3)
假设我的评论是正确的,您可以使用这样的Streams:
hierarchalMap.entrySet()
.stream()
.flatMap(entry -> entry.getValue()
.stream()
.map(i -> new AbstractMap.SimpleEntry<>(entry.getKey(), i)))
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
这假设没有重复项,也没有空值。
答案 1 :(得分:2)
我认为这应该做你需要的:
<input
ng-value="account.rowIsSelected"
name="selectedAccount"
ng-change="vm.selectAccount(account)"
type="radio">
通常情况下,使用Java 8流时,必须将更多逻辑放入操作的“collect”部分,而不是使用另一种语言的等效结构,部分原因是缺少方便的元组类型。直观地说,创建一个对列表然后将它们收集到一个映射中似乎更合理,但最终会比在public Map<Integer, Object> normalizeJava8(Map<Object, List<Integer>> hierarchalMap ) {
return hierarchalMap
.entrySet()
.stream()
.collect(
HashMap::new,
(map, entry) ->
entry.getValue().forEach(i -> map.put(i, entry.getKey())),
HashMap::putAll);
}
答案 2 :(得分:1)
使用流和Java 9:
Map<Integer, Object> normalizedMap = hierarchalMap.entrySet().stream()
.flatMap(e -> e.getValue().stream().map(i -> Map.entry(i, e.getKey())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
这几乎与this answer完全相同,只是我使用Map.entry()
方法创建对并将整数作为键。
在没有溪流的情况下,这是另一种不那么冗长的方式:
Map<Integer, Object> normalizedMap = new HashMap<>();
hierarchalMap.forEach((k, v) -> v.forEach(i -> normalizedMap.put(i, k)));
答案 3 :(得分:0)
您可以在Java 8中使用两个便利收集器,它们不仅限于地图。
public static <T, K, V> Collector<T, ?, Map<K, V>> flatInverseMapping(Function<? super T, ? extends Stream<? extends K>> keyStreamFunction,
Function<? super T, ? extends V> valueFunction) {
return Collector.of(HashMap::new,
(m, v) ->
keyStreamFunction.apply(v).forEach(innerV -> m.put(innerV, valueFunction.apply(v))),
(m1, m2) -> {
m1.putAll(m2);
return m2;
});
}
public static <T, K, V> Collector<T, ?, Map<K, V>> flatInverseMapping(Function<? super T, ? extends Collection<? extends K>> keyStreamFunction,
Function<? super T, ? extends V> valueFunction) {
return Collector.of(HashMap::new,
(m, v) ->
keyStreamFunction.apply(v).forEach(innerV -> m.put(innerV, valueFunction.apply(v))),
(m1, m2) -> {
m1.putAll(m2);
return m2;
});
}
由于流和集合都具有forEach,因此除了输入对象外,这两种实现都相同。
为简要说明其工作方式,收集器的输出是由两个函数的输出定义的K和V(键和值)参数的映射。对于流中从输入对象派生的每个键值,将应用相同的值函数,以便在共享键之间使用一致的值反转映射。请注意,如果流中有多个项目可以解析为相同的键,则不会像正常的toMap实现那样抛出合并异常。 BiConsumer将需要更改为保持该行为:
(var1, var2) -> {
Iterator<Map.Entry<K,V>> var3 = var2.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry<K,V> var4 = var3.next();
var1.merge(var4.getKey(), var4.getValue(), (v0, v1) -> {
throw new IllegalStateException(String.format("Duplicate key %s", v0));
});
}
return var1;
}
作为参考,它实际上是从Collectors.toMap代码复制的。