如何使用streams在Java8中迭代ArrayList的HashMap
我有以下数据集,其中Key为String,value为值列表 我想用key和list的每个值作为方法的参数来调用一个方法。迭代所有键。我可以使用两个forEach循环来完成它,如下面的示例所示。 我想知道我们是否可以在Java8中使用streams和flatMap编写相同的逻辑,而无需forEach内部循环?谢谢如何使用streams在Java8中迭代ArrayList的HashMap,java,java-8,java-stream,Java,Java 8,Java Stream,我有以下数据集,其中Key为String,value为值列表 我想用key和list的每个值作为方法的参数来调用一个方法。迭代所有键。我可以使用两个forEach循环来完成它,如下面的示例所示。 我想知道我们是否可以在Java8中使用streams和flatMap编写相同的逻辑,而无需forEach内部循环?谢谢 Map<String,ArrayList<String>> xhashMap ; if(xhashMap!=null) { xhashMap.forEa
Map<String,ArrayList<String>> xhashMap ;
if(xhashMap!=null) {
xhashMap.forEach((k,l)-> {
if(k.equals("ax")){
l.forEach(v->{
method1(v,AA.class);
}
}
if(k.equals("bx")){
l.forEach(v->{
method1(v,BB.class);
}
}
});
}
Map-xhashMap;
if(xhashMap!=null){
xhashMap.forEach((k,l)->{
如果(k等于(“ax”)){
l、 forEach(v->{
方法1(v,AA级);
}
}
如果(k等于(“bx”)){
l、 forEach(v->{
方法1(v,BB级);
}
}
});
}
是的,我们不能用流API编写它,但也没有太好
由于您正在执行副作用而不收集结果,Stream
基本上是:
xhashMap.entrySet()
.stream()
.forEach(e -> ...);
不幸的是,在forEach
中包含相同的逻辑
实际上,此时您甚至可以跳过流
创建,因为您可以在不创建流的情况下执行forEach
:
xhashMap.entrySet()
.forEach(e -> ...);
无论您是使用for
循环、forEach
还是流
API,这都无关紧要。在所有情况下,您都在迭代映射
以将每个键与某个值进行比较,这会扭曲映射的概念,从而将键与值关联并提供(通常比线性更好)查找方法
此外,您应该使用映射
,而不是引用像ArrayList
这样的实现类型,并且首先不要让它为null
,而不是让它稍后检查null
如果您遵循这些建议,您的代码将变为
Map<String, List<String>> xhashMap;
// always initialize the map to a non-null reference
xhashMap.getOrDefault("ax", Collections.emptyList())
.forEach(v -> method1(v, AA.class));
xhashMap.getOrDefault("bx", Collections.emptyList())
.forEach(v -> method1(v, BB.class));
Map-xhashMap;
//始终将映射初始化为非空引用
xhashMap.getOrDefault(“ax”,Collections.emptyList())
.forEach(v->method1(v,AA.class));
xhashMap.getOrDefault(“bx”,Collections.emptyList())
.forEach(v->method1(v,BB.class));
如变量名所示,如果映射是哈希映射,则两次查找将具有O(1)
时间复杂度,但即使是TreeMap
具有O(log(n))
复杂度也比在映射上迭代并比较所有键要好
只要操作包含一个具有不同参数的唯一方法调用,重复使用公共代码就没有多大好处,因为共享代码要复杂得多。确保可以使用flatMap和闭包来完成
xHashMap.entrySet().stream()
.flatMap(e -> e.getValue().stream()
.<Runnable>map(v -> () -> {
final String k = e.getKey();
if (k.equals("ax")) {
method1(v, AA.class);
}
if (k.equals("bx")) {
method1(v, BB.class);
}
})
)
.forEach(Runnable::run);
xHashMap.entrySet().stream()
.flatMap(e->e.getValue().stream())
.map(v->()->{
最后一个字符串k=e.getKey();
如果(k等于(“ax”)){
方法1(v,AA级);
}
如果(k等于(“bx”)){
方法1(v,BB级);
}
})
)
.forEach(Runnable::run);
为什么要使用流?流实现似乎更容易混淆;尤其是当您映射到不同的类类型时。我认为如果我们有大量数据流,在这种情况下会表现良好。但我不确定。所以只需检查一下。您认为我做得正确,不能在流中完成。我没有使用streams API的经验。刚开始学习鉴于您正在从内存中已存在的映射中播种数据,使用流可能不会更好-上面的方法可能更好。好的,谢谢您的输入。为什么要在映射上迭代以查找特定键?Map.getOrDefault(“ax”),emptyList()).forEach(v->method1(v,AA.class))
或者,如果缺少键是一种异常情况,只需map.get(“ax”).forEach(…)
谢谢@Grzegorz,我同意。我们现在不需要流。您的语句。entryset().forEach(e->…)。我必须再次检查下面基于键的第二个参数。例如,在键“ax”的情况下,它将是AA.class。这就是我必须显式检查键值的原因。@techi e是一个条目,它同时包含键和值-本质上它并不比您的解决方案好