5

I have a for loop iterating over a Integer [][]map. Currently is like this:

for(int i = 0; i < rows; i++) {
    for(int j = 0; j < columns; j++) {
        if(map[i][j] == 1)
            q.add(new Point(i,j));
    }
}        

Instead of 2d array, suppose I have List<List<Integer>> maps2d. How would I do that with streams?

So far I got this:

maps2d.stream()
      .forEach(maps1d -> maps1d.stream()
                               .filter(u -> u == 1)
                               .forEach(u -> {

                               }
      )
);

Is it correct so far? If yes, how do I count i and j in order to create the new Point(i,j) and add it to q ?

0

1 Answer 1

5

If you really want to use streams for the same purpose then one option is to use nested IntStreams to iterate over the indices. As an example:

public static List<Point> foo(List<List<Integer>> map) {
  return IntStream.range(0, map.size()) // IntStream
      .mapToObj(
          i ->
              IntStream.range(0, map.get(i).size())
                  .filter(j -> map.get(i).get(j) == 1)
                  .mapToObj(j -> new Point(i, j))) // Stream<Stream<Point>>
      .flatMap(Function.identity()) // Stream<Point>
      .collect(Collectors.toList()); // List<Point>
}

Personally, I don't find that tremendously readable. Note you can still use nested for loops with your list, similar to your current solution:

public static List<Point> foo(List<List<Integer>> map) {
  List<Point> result = new ArrayList<>();
  for (int i = 0; i < map.size(); i++) {
    List<Integer> inner = map.get(i);
    for (int j = 0; j < inner.size(); j++) {
      if (inner.get(j) == 1) {
        result.add(new Point(i, j));
      }
    }
  }
  return result;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for clarifying that a normal for loop answer would be more readable while still answering the question. A normal for loop is far more readable and this is an example of the stream API being possible, but takes away from readability.
Yikes. I know the authors were operating under a crazy number of constraints when designing the stream library, but man this code is just nasty.
My main gripe is that there needs to be a distinction between Stream and IntStream. In Java, people are always raving about how awesome objects are, how allocations are cheap and GC is "so fast now." Yet when it comes down to it, IntStream had to be invented, with all the work necessary to convert back/forth to it, all because the JVM doesn't have user-definable inline-able value types, which would make Stream<int>/Stream<double> possible and remove the need for IntStream/DoubleStream/ etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.