Home > Mobile >  How to use Stream to get all Lists from a nested List that match a specific condition?
How to use Stream to get all Lists from a nested List that match a specific condition?

Time:07-19

How can I achieve the same logic in my code using only Streams, without the for loop as shown in my code below?

I have tried using flatMap, but I get stuck on the condition part, since allMatch() only returns a boolean.

How can I retrieve all the rows from the nested ArrayList that passes the condition without using for loop?

ArrayList<ArrayList<Tile>> completeRows = new ArrayList<>();
for (ArrayList<Tile> rows: getGridTiles()) {
    if (rows.stream().allMatch(p -> p.getOccupiedBlockType() != BlockType.EMPTY)) {
        completeRows.add(rows);
    }
}

CodePudding user response:

You can apply filter() with a nested stream (exactly the same as you've used as a condition in your code) passed to it as a Predicate to verify that a list consists of only non-empty tiles.

And then collect all the lists (rows) that have passed the predicate into a List using collect().

public static List<List<Tile>> getNonEmptyRows(List<List<Tile>> rows) {
    
    return rows.stream()
        .filter(row -> row.stream().allMatch(tile -> tile.getOccupiedBlockType() != BlockType.EMPTY))
        .collect(Collectors.toList()); // or .toList() with Java 16 
}

I have tried using flatMap

You need to use flatMap when your goal is to flatten the steam of collections (or objects holding a reference to a collection) to a stream of elements of these collections. In these case, turn a stream of lists of tiles Stream<List<Tile>> into a stream of tiles Stream<Tile>.

Judging by your code, it's not you what you want because you're accumulating the rows (lists of tiles) into another list and not "flattening" them.

But just in case, that's how it can be done:

public static List<Tile> getNonEmptyTiles(List<List<Tile>> rows) {
    
    return rows.stream()
        .filter(row -> row.stream().allMatch(tile -> tile.getOccupiedBlockType() != BlockType.EMPTY))
        .flatMap(List::stream)
        .collect(Collectors.toList()); // or .toList() with Java 16 
}

Sidenote: leverage abstract data types - write your code against interfaces. What does it mean to "program to an interface"?

  • Related