简体   繁体   English

如何使用Java中的流从两个数组中创建映射?

[英]How to create a map out of two arrays using streams in Java?

Say I have two arrays of Double 说我有两个Double数组

Double[] a = new Double[]{1.,2.,3.};
Double[] b = new Double[]{10.,20.,30.};

Using Java streams , how do I create a map ( Map<Double,Double> myCombinedMap; ) that combines the two arrays for example in the following way: 使用Java流 ,如何创建一个映射( Map<Double,Double> myCombinedMap; ),该映射例如通过以下方式组合两个数组:

System.out.println(myCombinedMap);
{1.0=10.0, 2.0=20.0, 3.0=30.0}

I guess am looking for something similar to Python zip with Java streams, or an elegant workaround. 我猜想在寻找类似于带Java流的Python zip的东西,还是一种优雅的解决方法。

I think this question differs from this one (pointed out as possible duplicate) because is centered on Java8 streams, which were not yet available at the time the possible duplicate question was asked. 我觉得从这个问题的不同一个(指出了可能重复的),因为在Java8流为中心,这是尚未公布在可能重复的问题被问的时间。

use IntStream and collect to a map: 使用IntStream并收集到地图:

IntStream.range(0, a.length)
         .boxed()
         .collect(toMap(i -> a[i], i -> b[i]));

I'd probably go for the solution by Aomine myself. 我可能会自己去寻求Aomine的解决方案。 For the sake of completeness, if you don't like the boxing of the IntStream (it feels unnecessary), you may do for example: 为了完整起见,如果您不喜欢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);

Output from this snippet is: 该代码段的输出为:

{1.0=10.0, 2.0=20.0, 3.0=30.0} {1.0 = 10.0,2.0 = 20.0,3.0 = 30.0}

As the code stands, there is an important difference between the working of the code by Aomine and my code though: That code checks for duplicate keys and objects if there are any. 就目前的代码而言,Aomine的代码与我的代码之间存在重要的区别:该代码检查是否有重复的键和对象。 My code tacitly drops them. 我的代码默认将其删除。 My code could be extended to include the check too, but it would add a complication that I don't think we want. 我的代码也可以扩展为包括检查,但是这会增加我不希望的复杂性。

Why the boxed() call helps: the collectors in the Collectors class, of which Aomine used toMap , work only on streams of objects, not on streams of primitives like IntStream . 为什么boxed()调用有帮助:Aomine曾经使用过toMapCollectors类中的Collectors仅适用于对象流,而不适用于IntStream之类的基元流。

We can do it using Collectors.toMap() from an IntStream which supplies the indices: 我们可以使用提供索引的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]));

We could also map the IntStream to a Stream of Map.Entry<Double, Double> objects then use Collectors.toMap() : 我们还可以将IntStream映射到Map.Entry<Double, Double>对象的Stream,然后使用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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM