如何使用流解决以下练习
Posted
技术标签:
【中文标题】如何使用流解决以下练习【英文标题】:How can I solve the following exercise with streams 【发布时间】:2021-12-23 00:31:03 【问题描述】:在下面的练习中,我应该保留所有包含 SmartLamps 的房间。我怎样才能用流解决这个问题?由于每个 SmartLamp 都有属性 Room,我需要流过房间和灯。我试图用 anyMatch 来做,但找不到可行的解决方案。有人可以帮忙吗? (我知道如何在没有流的情况下解决它)
public class SmartHome
private final List<Room> rooms;
private final List<SmartLamp> lamps;
public void deleteRooms()
rooms.stream().anyMatch(lamps.stream().map(SmartLamp::getRoom));
代码给出错误: “类型不匹配:无法从 Stream 转换为 Predicate”
【问题讨论】:
Collection
s like List
s 有一个方法removeIf
另外,Stream.filter 允许您仅将匹配谓词的元素传递给管道中的下一个操作。
您可以使用.stream()
过滤掉坏房间(.filter()
)。之后,您可以收集房间并将其分配给您的this.rooms
。
【参考方案1】:
anyMatch
的使用并没有错,只是用错了地方:
public void deleteRooms()
rooms = rooms.stream().filter(r -> lamps.stream().map(SmartLamp::getRoom).anyMatch(r::equals);
但以上内容并不理想,因为您必须遍历每个房间的灯列表。预先提取出现在灯列表中的所有房间会有所帮助:
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());
或使用 List.removeIf
public void deleteRooms()
Set<Room> smartRooms = lamps.stream().map(SmartLamp::getRoom).collect(Collectors.toSet());
rooms.removeIf(r -> !smartRomms.contains(r));
【讨论】:
这看起来很棒!但是带有过滤器的第二个示例在不应该使用时使用 not 运算符!流过滤器结果包含所有返回 true :) @bgore 感谢您指出这一点。复制粘贴,没注意。 虽然我可以只用流解决这个问题,但我认为这是不可能的,我们也总是需要使用集合..我正确吗? 你的removeIf
不等于rooms.retainAll(smartRomms);
吗?【参考方案2】:
我应该保留所有装有 SmartLamp 的房间。
好的,所以你可以这样做......
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;
这能解决您的问题吗?在 cmets 中告诉我。
【讨论】:
没有房间没有灯属性...灯有房间属性 添加了一个编辑。看看吧 我是否更正了此方法只会返回相关房间,但是我需要将该方法应用于 Listlamps.stream().map(SmartLamp::getRoom).anyMatch(rooms::contains);
谓词不需要流,您需要创建一个 lambda room -> ...
。
但是您已经为映射灯制作了一个流,所以我将从该流开始。真的contains
不是很好,但已经足够好了。
Set<Room>
会更好。
【讨论】:
【参考方案4】:你可以试试
lamps.stream()
.map(SmartLamp::getRoom)
.filter(rooms::contains)
.collect(Collectors.toSet());
【讨论】:
不错!但这之后需要进行额外的操作,因为我需要更改 List我相信 anymatch 不是你想要的。任何匹配都是一个流方法,如果流中的任何内容与您想要的匹配,则返回 true 或 false。
但不管你想要一个谓词
它的形式
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();
第二行中的房间表示流中的对象。在你的情况下是一个房间。
第一行是保存所有房间的列表,所以你不需要为每个房间映射。
您可以在此处阅读有关谓词的更多信息 https://www.geeksforgeeks.org/java-8-predicate-with-examples/
【讨论】:
以上是关于如何使用流解决以下练习的主要内容,如果未能解决你的问题,请参考以下文章