JavaNovice
JavaNovice

Reputation: 1142

Java Streams - map method of a nested stream not working like expected

I have the code below and I was hoping that finalList would get populated with the result of the filter operation of the inner stream, but it does not print anything.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainClass {

    public static void main(String[] args) {
        ArrayList<String> finalList = new ArrayList<>();
        ArrayList<String> l = new ArrayList<>();
        l.add("c");
        l.add("e");

        ArrayList<String> l1 = new ArrayList<>();
        l1.add("a");
        l1.add("b");

        Map<String, Integer> map1 = new HashMap<>();
        map1.put("a-c", 1);
        map1.put("b-d", 2);

        l1.stream()
                .map(c-> {
                    System.out.println("inside map" + c);
                    l.stream().filter(s -> 
                        map1.containsKey(c+"-"+s)).forEach(f-> {

                             System.out.println("f value is" + f);
                              finalList.add(f);
                        });
                        return null;
                      });


        System.out.println("Final List is:" + finalList);

      }
     }

I see none of the sysouts within the map method. Please help me understand why this is not executing any code?

The output I get is:

Final List is:[]

Upvotes: 1

Views: 3012

Answers (2)

Naman
Naman

Reputation: 31868

That is because Stream#map is an intermediate operation and you're currently ignoring it all together.

You should preferably use a terminal operation to execute the block of code that you've included within the map operation. A simple way of doing that could be

l1.stream().map(c -> {
    System.out.println("inside map" + c);
    l.stream().filter(s ->
            map1.containsKey(c + "-" + s)).forEach(f -> {
        System.out.println("f value is" + f);
        finalList.add(f);
    });
    return null;
}).forEach(a -> { }); // notice forEach doing nothing for now

Aside: What you're trying to achieve without the logging (print) statements can be written as

l1.forEach(a -> IntStream.range(0, l.size())
        .filter(b -> map1.containsKey(a + "-" + l.get(b)))
        .mapToObj(l::get)
        .forEach(finalList::add));

// Output: Final List is:[c]

Note: This would also help you in avoiding stateful operations performed within map.

Upvotes: 1

Nicholas K
Nicholas K

Reputation: 15423

You need to use for-each instead of map. The map returns Stream and unless you perform a terminal operation on the stream you won't get an output.

Use :

    l1.stream().forEach(c -> {
        System.out.println("inside map" + c);
        l.stream().filter(s -> map1.containsKey(c + "-" + s)).forEach(f -> {

            System.out.println("f value is" + f);
            finalList.add(f);
        });
    });

Upvotes: 3

Related Questions