英文:
Java how to stream a list inside a list for an object?
问题
所以我在另一个列表中存储了一些列表。
而在这些列表内部,有不同的对象。
我想根据属性获取特定的对象。
Human robert = building.getRoomList()
.stream()
.filter(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert")))
.findFirst().get();
为什么它不起作用呢?
英文:
So I have lists stored inside of another list.
And inside of that lists there a different objects.
I want to get a specific object based on an attribute.
Human robert = building.getRoomList()
.stream()
.filter(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert")))
.findFirst().get();
Why doesn't it work?
答案1
得分: 2
尝试一下这样写:
Human robert = building.getRoomList().stream()
.map(Room::getRoomList)
.flatMap(Collection::stream)
.filter(human -> human.getName().equals("Robert"))
.findFirst()
.orElseThrow(() -> new RuntimeException("找不到Robert!"));
英文:
Try this:
Human robert = building.getRoomList().stream()
.map(Room::getRoomList)
.flatMap(Collection::stream)
.filter(human -> human.getName().equals("Robert"))
.findFirst()
.orElseThrow(() -> new RuntimeException("Robert not found!"));
答案2
得分: 1
你可以使用 Stream.flatMap
来实现:
Optional<Human> robert = building.getRoomList().stream()
.flatMap(room -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst();
robert.ifPresent(r -> /* 对 Robert 做一些操作 */);
`Stream.flatMap` 将每个 `room` 映射为一个 `human` 流,返回的流由所有房间中的所有人组成,被平铺(即不作为子列表或子流)。
英文:
You can do it using Stream.flatMap
:
Optional<Human> robert = building.getRoomList().stream()
.flatMap(room -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst();
robert.ifPresent(r -> /* do something with Robert */);
Stream.flatMap
maps each room
to a stream of human
s and the returned stream consists of all the humans of all the rooms, flattened (i.e. not as sublists or substreams).
答案3
得分: 1
为什么它不起作用?
Stream::filter
需要一个 Predicate<T>
,并返回相同的 Stream<T>
。只要你在 filter
中嵌套了另一个 filter
,这永远不会起作用,因为外部一个需要 Predicate<T>
,而内部一个返回的是明显不兼容的 Stream<T>
。
你可能想使用 flatMap
:
Human robert = building.getRoomList()
.stream()
.flatMap(room -> room
.getEmployeeList()
.stream()
.filter(human -> human.getName()
.equals("Robert")))
.findFirst()
.orElse(null);
请记住,谓词 human -> human.getName().equals("Robert")
既不是对空值安全的,也不是对其名称为 null
的情况安全的。为了空值安全,可以这样使用 flatMap:
.flatMap(room -> room.getEmployeeList()
.stream()
.filter(Objects::nonNull)
.filter(human -> "Robert".equals(human.getName())))
英文:
> Why doesn't it work?
Stream::filter
requires a Predicate<T>
and returns the very same Stream<T>
. As long as you nest filter
in filter
, this would never work because the outer one requires Predicate<T>
while the inner one returns Stream<T>
which is clearly not compatible.
You might want to use flatMap
:
Human robert = building.getRoomList()
.stream() // Stream<Room>
.flatMap(room -> room // Stream<Human> flatmapped from:
.getEmployeeList() // .. for each Room get List<Human>
.stream() // .. for each Room have Stream<Human>
.filter(human -> human.getName() // .. for each Room keep the one named
.equals("Robert"))) // .. Robert
.findFirst() // find the first Robert, the Human
.orElse(null); // or result in null
Remember the predicate human -> human.getName().equals("Robert"))
is not null-safe neither when human
is null
nor when its name is null
. For the null-safety, flat-map like this:
.flatMap(room -> room.getEmployeeList()
.stream()
.filter(Objects::nonNull)
.filter(human -> "Robert".equals(human.getName())))
答案4
得分: 1
你只对 RoomList
执行了 .findFirst()
,但你还需要对每个 Room
的内部列表即 EmployeeList
执行 .findFirst()
,然后使用 .map()
将 Room
转换为 Human
,就像这样:
building.getRoomList()
.stream()
.map(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert"))
.findFirst().get())
.findFirst().get();
可以使用 flatMap
进行简化,先展平 EmployeeList
,然后执行 findFirst
:
building.getRoomList()
.flatMap(room -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst().get();
注意:最好使用 .orElse()
而不是调用 .get()
。
英文:
You are doing .findFirst()
on RoomList
only but you need to do .findFirst()
on inner list means EmployeeList
of every Room
also and transform Room
into Human
using .map()
, like
building.getRoomList()
.stream()
.map(room -> room.getEmployeeList()
.stream()
.filter(human -> human.getName().equals("Robert"))
.findFirst().get())
.findFirst().get();
Which can be simplified using flatMap
to flatten then EmployeeList
then get findFirst
building.getRoomList()
.flatMap(e -> room.getEmployeeList().stream())
.filter(human -> human.getName().equals("Robert"))
.findFirst().get();
Note: It's better to use .orElse()
rather calling .get()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论