假设我有两个
Double
数组
Double[] a = new Double[]{1.,2.,3.};
Double[] b = new Double[]{10.,20.,30.};
使用 Java 流,如何创建一个将两个数组组合在一起的映射 (
Map<Double,Double> myCombinedMap;
),例如通过以下方式:
System.out.println(myCombinedMap);
{1.0=10.0, 2.0=20.0, 3.0=30.0}
我想正在寻找类似于带有 Java 流的 Python zip 的东西,或者一个优雅的解决方法。
我认为这个问题与this一个不同(指出可能重复) 因为它以 Java8 流为中心,而在提出可能的重复问题时,这些流还不可用。
使用
IntStream
并收集到地图:
IntStream.range(0, a.length)
.boxed()
.collect(toMap(i -> a[i], i -> b[i]));
我可能会寻求青峰本人的解决方案。为了完整起见,如果你不喜欢
IntStream
的拳击(感觉没必要),你可以这样做:
Double[] a = new Double[]{1.,2.,3.};
Double[] b = new Double[]{10.,20.,30.};
Map<Double, Double> myMap = IntStream.range(0, a.length)
.collect(HashMap::new, (m, i) -> m.put(a[i], b[i]), Map::putAll);
System.out.println(myMap);
此片段的输出是:
{1.0=10.0, 2.0=20.0, 3.0=30.0}
就代码而言,Aomine 的代码和我的代码之间有一个重要的区别:该代码会检查重复的键和对象(如果有)。我的代码默认删除它们。我的代码也可以扩展以包含检查,但这会增加我认为我们不想要的复杂性。
为什么
boxed()
调用有帮助:Aomine 使用 Collectors
的 toMap
类中的收集器仅适用于对象流,而不是像 IntStream
这样的基元流。
我们可以使用提供索引的
Collectors.toMap()
中的 IntStream
来做到这一点:
Double[] a = new Double[]{1.,2.,3.};
Double[] b = new Double[]{10.,20.,30.};
Map<Double, Double> map =
IntStream.range(0, a.length)
//If you array has null values this will remove them
.filter(idx -> a[idx] != null && b[idx] != null)
.mapToObj(idx -> idx)
.collect(Collectors.toMap(idx -> a[idx], idx -> b[idx]));
我们还可以将
IntStream
映射到 Map.Entry<Double, Double>
对象流,然后使用 Collectors.toMap()
:
Double[] a = new Double[]{1.,2.,3.};
Double[] b = new Double[]{10.,20.,30.};
Map<Double, Double> map =
IntStream.range(0, a.length)
.filter(idx -> a[idx] != null && b[idx] != null)
.mapToObj(idx -> new AbstractMap.SimpleEntry<Double, Double>(a[idx], b[idx]))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Google Guava 库有
Streams.zip
方法,它将压缩两个流:
Map<Double, Double> myCombinedMap =
Streams.zip(Arrays.stream(a), Arrays.stream(b), Map::entry)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));