如何使用流解决以下练习

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

【问题讨论】:

Collections like Lists 有一个方法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 中告诉我。

【讨论】:

没有房间没有灯属性...灯有房间属性 添加了一个编辑。看看吧 我是否更正了此方法只会返回相关房间,但是我需要将该方法应用于 List 并使用流进行更改... 查看原帖的下一次编辑 现在解决你的问题了吗?【参考方案3】:
lamps.stream().map(SmartLamp::getRoom).anyMatch(rooms::contains);

谓词不需要流,您需要创建一个 lambda room -&gt; ...

但是您已经为映射灯制作了一个流,所以我将从该流开始。真的contains 不是很好,但已经足够好了。

Set&lt;Room&gt; 会更好。

【讨论】:

【参考方案4】:

你可以试试

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

【讨论】:

不错!但这之后需要进行额外的操作,因为我需要更改 List 房间。过滤是完美的,但我可以在这个流中以某种方式对房间应用任何操作吗? (我认为不可能) 是的。那么你应该使用 flatmap() 。【参考方案5】:

我相信 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/

【讨论】:

以上是关于如何使用流解决以下练习的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Python进行单元测试建议收藏

如何使用 Google OR 工具解决流游戏?

如何找到路径流并使用猪或蜂巢对它们进行排名?

如何正确使用 CuPy 流

Java学习日记-----IO流 练习

c++使用文件流fstream换行符的保存,该如何解决