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"?