Java 8 获取列表中的所有元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35495906/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:11:53  来源:igfitidea点击:

Java 8 get all elements in list

javajava-8java-stream

提问by tsingh

I have a List of Objects where each object that returns List<String>. How can I use Java 8 streams to get only one List<String>?

我有一个对象列表,其中每个返回List<String>. 如何使用 Java 8 流只获得一个List<String>

Contactclass has the following method;

Contact类有以下方法;

public List<String> getSharedFriendsIds() {
    return sharedFriendsIds;
}

And I have

我有

List<Contact> contactsList;

What I was trying was

我正在尝试的是

List<String> sharedContacts = contactsList.stream()
    .map(Contact::getSharedFriendsIds)
    .sequential()
    .collect(Collectors.toList());

But above line is not returning List<String>but rather List<List<String>>which is not what I want.

但上面的线没有返回 List<String>,而是 List<List<String>>这不是我想要的。

回答by bur?quete

You should use .flatMap()to create a single list from the sharedFriendsIdslist that is contained in each Contactobject from the main list contactsList. Please check;

您应该使用从主列表的每个对象中包含.flatMap()sharedFriendsIds列表创建单个Contact列表contactsList。请检查;

List<String> sharedContacts = contactsList.stream()
        .map(Contact::getSharedFriendsIds)
        .filter(Objects::nonNull)
        .flatMap(Collection::stream)
        .sorted().collect(Collectors.toList());

The .filter()call is for the case when there is any Contactwith sharedFriendsIds == nullin the list, since that would cause NPEin the next line, we ought to filter those out. There are other ways to achieve that like;

.filter()调用适用于列表中有任何Contactwith的情况sharedFriendsIds == null,因为这会导致NPE下一行,我们应该将它们过滤掉。还有其他方法可以实现这一点;

- Optional

—— Optional

    List<String> sharedContacts = contactsList.stream()
            .flatMap(contacts -> Optional.ofNullable(contacts.getSharedFriendsIds())
                    .map(Collection::stream).orElseGet(Stream::empty))
            .sorted().collect(Collectors.toList());

  Where the filtering of null `sharedFriendsIds` are done in such a way that 
 they are absorbed into the `flatMap` logic as empty streams.

- emptyIfNull()

—— emptyIfNull()

You can include collections dependency from apache.commonsand use CollectionUtils.emptyIfNullmethod as follows;

您可以按如下方式包含来自apache.commons和使用CollectionUtils.emptyIfNull方法的集合依赖项;

    public static <T> Stream<T> collectionAsStream(Collection<T> collection) {
        return emptyIfNull(collection).stream();
    }

then call this from original stream like;

然后从原始流中调用它;

     List<String> sharedContacts = contactsList.stream()
             .map(Contact::getSharedFriendsIds)
             .flatMap(Foo::collectionAsStream)
             .sorted().collect(Collectors.toList());

Also you used .sequentialfor the sort logic, I guess, you should've used .sortedmethod, since sequential is for triggering non-parallel usage, which is already the default configuration of a Stream.

您还用于.sequential排序逻辑,我想,您应该使用.sorted方法,因为顺序用于触发非并行使用,这已经是Stream.

回答by dmitryvinn

There is no reason to use .sequential()here, streams are sequential by default.

没有理由在.sequential()这里使用,默认情况下流是顺序的。

List<String> sharedContacts = contactsList.stream()
        .map(Contact::getSharedFriendsIds)
        .filter(Objects::nonNull)
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

In natural order;

按自然顺序;

List<String> sharedContacts = contactsList.stream()
        .map(Contact::getSharedFriendsIds)
        .filter(Objects::nonNull)
        .flatMap(Collection::stream)
        .sorted().collect(Collectors.toList());

回答by Federico Peralta Schaffner

A pattern I've found very useful is to let the parent class (in this case the Contactclass) create and return the streams of children objects (in this case the share friends ids):

我发现一个非常有用的模式是让父类(在本例中为Contact类)创建并返回子对象流(在本例中为共享朋友 ID):

public class Contact {

    private List<String> sharedFriendsIds;

    public Stream<String> sharedFriendsIds() {
        return sharedFriendsIds == null ? Stream.empty() : sharedFriendsIds.stream();
    }

    public List<String> getSharedFriendsIds() {
        return sharedFriendsIds;
    }
}

The convention is to name the method that returns the stream as the attribute being streamed. This method already contains the null-check.

约定是将返回流的方法命名为正在流式传输的属性。此方法已包含空检查。

Then, getting the shared friends ids for all contacts is much easier:

然后,获取所有联系人的共享好友 ID 就容易多了:

List<String> sharedContacts = contactsList.stream()
        .flatMap(Contact::sharedFriendsIds)
        .collect(Collectors.toList());

You need to use flatMap()in order to flattenthe elements of the child list into a single list, otherwise you'd get a list of streams.

您需要使用flatMap()以将子列表的元素展平为单个列表,否则您将获得一个流列表。

Note 1: you don't need to use sequential(), since using stream()on the list of contacts already returns a sequential stream.

注意 1:您不需要使用sequential(),因为stream()在联系人列表上使用已经返回一个顺序流。

Note 2: if you want the final list to be sorted, then you should use sorted()on the stream:

注意 2:如果您希望对最终列表进行排序,那么您应该sorted()在流上使用:

List<String> sharedContacts = contactsList.stream()
        .flatMap(Contact::sharedFriendsIds)
        .sorted().collect(Collectors.toList());