CuriousIndeed
CuriousIndeed

Reputation: 131

How can I solve the following exercise with streams

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

Answers (5)

Eritrean
Eritrean

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

Deep
Deep

Reputation: 152

You can try

lamps.stream()
         .map(SmartLamp::getRoom)
         .filter(rooms::contains)
         .collect(Collectors.toSet());

Upvotes: 1

Arthur Klezovich
Arthur Klezovich

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

bgore
bgore

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

Joop Eggen
Joop Eggen

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

Related Questions