我有一个对象列表,其中每个对象返回List<String>
。
如何使用Java 8流只获得一个List<String>
?
Contact
类有以下方法;
public List<String> getSharedFriendsIds() {
return sharedFriendsIds;
}
我有
List<Contact> contactsList;
我在尝试的是
List<String> sharedContacts = contactsList.stream()
.map(Contact::getSharedFriendsIds)
.sequential()
.collect(Collectors.toList());
但是上面的行不会返回List<String>
而是返回List<List<String>>
这不是我想要的。
答案 0 :(得分:11)
您应该使用.flatMap()
从主列表sharedFriendsIds
中的每个Contact
对象中包含的contactsList
列表创建单个列表。请检查以下内容;
List<String> sharedContacts = contactsList.stream()
.filter(contacts -> contacts.getSharedFriendsIds() != null)
.flatMap(contacts -> contacts.getSharedFriendsIds().stream())
.sorted().collect(Collectors.toList());
.filter()
调用适用于列表中与sharedFriendsIds == null
有任何联系的情况,因为这会在下一行中导致NPE,我们应该将其过滤掉。还有其他方法可以实现这一点;
List<String> sharedContacts = contactsList.stream()
.flatMap(contacts -> Optional.ofNullable(contacts.getSharedFriendsIds())
.map(List::stream).orElseGet(Stream::empty))
.sorted().collect(Collectors.toList());
对null sharedFriendsIds
的过滤以这样的方式完成,即它们作为空流被吸收到flatMap
逻辑中。
你也使用.sequential
作为排序逻辑,我想你应该使用.sorted
方法,因为顺序用于触发非并行使用,这已经是默认配置默认Stream
。
答案 1 :(得分:5)
此处没有理由使用.sequential()
,默认情况下,流是顺序的。
List<String> sharedContacts = contactsList.stream()
.map(Contact::getSharedFriendsIds)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList());
按自然顺序;
List<String> sharedContacts = contactsList.stream()
.map(Contact::getSharedFriendsIds)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.sorted().collect(Collectors.toList());
答案 2 :(得分:2)
我发现非常有用的模式是让父类(在本例中为Contact
类)创建并返回子对象流(在本例中是共享朋友ID): / p>
public class Contact {
private List<String> sharedFriendsIds;
public Stream<String> sharedFriendsIds() {
return sharedFriendsIds == null ? Stream.empty() : sharedFriendsIds.stream();
}
public List<String> getSharedFriendsIds() {
return sharedFriendsIds;
}
}
约定是将返回流的方法命名为要流式传输的属性。此方法已包含空检查。
然后,为所有联系人获取共享的朋友ID更容易:
List<String> sharedContacts = contactsList.stream()
.flatMap(Contact::sharedFriendsIds)
.collect(Collectors.toList());
您需要使用flatMap()
将子列表的元素展平到一个列表中,否则您将获得一个流列表。
注1:您不需要使用sequential()
,因为在联系人列表中使用stream()
已经返回了顺序流。
注意2:如果您希望对最终列表进行排序,那么您应该在流上使用sorted()
:
List<String> sharedContacts = contactsList.stream()
.flatMap(Contact::sharedFriendsIds)
.sorted().collect(Collectors.toList());