简体   繁体   中英

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

Say I have two arrays of 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:

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.

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.

use IntStream and collect to a map:

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

I'd probably go for the solution by Aomine myself. For the sake of completeness, if you don't like the boxing of the IntStream (it feels unnecessary), you may do for example:

    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}

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. 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 .

We can do it using Collectors.toMap() from an IntStream which supplies the indices:

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() :

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));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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