Reputation: 131
In the following exercise I should keep all the Rooms, which have SmartLamps in it. How can I solve this with streams? Since each SmartLamp has attribute Room I need to stream over rooms and lamps. I tried to do it with anyMatch, but cannot find a working solution. Can somebody help? ( I know how to solve it without streams)
public class SmartHome {
private final List<Room> rooms;
private final List<SmartLamp> lamps;
public void deleteRooms() {
rooms.stream().anyMatch(lamps.stream().map(SmartLamp::getRoom));
}
}
Code gives error: "Type mismatch: cannot convert from Stream to Predicate<? super Room>"
Upvotes: 0
Views: 106
Reputation: 16498
It was not wrong to use anyMatch
but only at the wrong place:
public void deleteRooms() {
rooms = rooms.stream().filter(r -> lamps.stream().map(SmartLamp::getRoom).anyMatch(r::equals);
}
but the above is not ideal since you have to iterate over the list of lamps for each room. Extracting all rooms which appear in the lamps list beforehand can help:
public void deleteRooms() {
Set<Room> smartRooms = lamps.stream().map(SmartLamp::getRoom).collect(Collectors.toSet());
rooms = rooms.stream().filter(r -> smartRomms.contains(r)).collect(Collectors.toList());
}
or using List.removeIf
public void deleteRooms() {
Set<Room> smartRooms = lamps.stream().map(SmartLamp::getRoom).collect(Collectors.toSet());
rooms.removeIf(r -> !smartRomms.contains(r));
}
Upvotes: 3
Reputation: 152
You can try
lamps.stream()
.map(SmartLamp::getRoom)
.filter(rooms::contains)
.collect(Collectors.toSet());
Upvotes: 1
Reputation: 2819
I should keep all the Rooms, which have SmartLamps in it.
OK, so you can do like this ...
public class SmartHome {
private final List<Room> rooms;
private final List<SmartLamp> lamps;
void deleteRoomsWithoutSmartLamps() {
var goodRooms = roomsWithSmartLamps();
// This line will remove the bad rooms from the list
rooms = rooms.stream().filter( r -> goodRooms.contains(r)).collect(toList())
}
// This method gives you a list of rooms with smart lamps
public List<Room> roomsWithSmartLamps() {
var goodRooms = lamps.stream().filter( lamp -> lamp.isSmartLamp() ).map(lamp -> lamp.getRoom()).filter(room != null)collect(toList());
return goodRooms;
}
}
Does this solve your problem ? Tell me in the comments.
Upvotes: 2
Reputation: 98
I believe anymatch isnt what you would like here. Any match is a stream method that returns true or false if anything in the stream matches what you want.
But regardless you would want a Predicate
which is of the form
List<Room> lampRoomList = lamps.stream().map(SmartLamp::getRoom).ToList()
//predicate is in the filter method
List<Room> roomsWithLamps = rooms.stream().filter(room.toroom -> lampRoomList.Contains(Room)).toList();
where room in the second line means object in the stream. in your case a room.
The first line is to hold the list of all rooms in lamps so you do not need to to the mapping for every room.
you can read more about predicates here https://www.geeksforgeeks.org/java-8-predicate-with-examples/
Upvotes: 0
Reputation: 109567
lamps.stream().map(SmartLamp::getRoom).anyMatch(rooms::contains);
The predicate does not expect a stream, you would need to make a lambda room -> ...
.
However you already have to make a stream for mapping lamps, so I would start with that stream. And really contains
is not very good, but fine enough.
A Set<Room>
would be better.
Upvotes: 1