如果我有一个List<List<Object>>,我如何使用Java8的特性将其转换为包含相同迭代顺序的所有对象的List<Object>?


当前回答

正如@Saravana提到的:

flatmap更好,但也有其他方法可以实现

 listStream.reduce(new ArrayList<>(), (l1, l2) -> {
        l1.addAll(l2);
        return l1;
 });

综上所述,有以下几种方法可以实现这一点:

private <T> List<T> mergeOne(Stream<List<T>> listStream) {
    return listStream.flatMap(List::stream).collect(toList());
}

private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
    List<T> result = new ArrayList<>();
    listStream.forEach(result::addAll);
    return result;
}

private <T> List<T> mergeThree(Stream<List<T>> listStream) {
    return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
        l1.addAll(l2);
        return l1;
    });
}

private <T> List<T> mergeFour(Stream<List<T>> listStream) {
    return listStream.reduce((l1, l2) -> {
        List<T> l = new ArrayList<>(l1);
        l.addAll(l2);
        return l;
    }).orElse(new ArrayList<>());
}

private <T> List<T> mergeFive(Stream<List<T>> listStream) {
    return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}

其他回答

您可以使用flatMap将内部列表(在将其转换为流之后)展平为单个流,然后将结果收集到列表中:

List<List<Object>> list = ...
List<Object> flat = 
    list.stream()
        .flatMap(List::stream)
        .collect(Collectors.toList());

flatmap更好,但也有其他方法可以实现

List<List<Object>> listOfList = ... // fill

List<Object> collect = 
      listOfList.stream()
                .collect(ArrayList::new, List::addAll, List::addAll);

扩展Eran的答案,这是最重要的答案,如果你有一堆层次的列表,你可以保持它们的平面映射。

如果需要的话,这还提供了一种方便的过滤方法,可以在你深入图层时进行过滤。

例如:

List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...

List<Object> objectList = multiLayeredList
    .stream()
    .flatmap(someList1 -> someList1
        .stream()
        .filter(...Optional...))
    .flatmap(someList2 -> someList2
        .stream()
        .filter(...Optional...))
    .flatmap(someList3 -> someList3
        .stream()
        .filter(...Optional...))
    ...
    .collect(Collectors.toList())

这在SQL中类似于在SELECT语句中包含SELECT语句。

正如@Saravana提到的:

flatmap更好,但也有其他方法可以实现

 listStream.reduce(new ArrayList<>(), (l1, l2) -> {
        l1.addAll(l2);
        return l1;
 });

综上所述,有以下几种方法可以实现这一点:

private <T> List<T> mergeOne(Stream<List<T>> listStream) {
    return listStream.flatMap(List::stream).collect(toList());
}

private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
    List<T> result = new ArrayList<>();
    listStream.forEach(result::addAll);
    return result;
}

private <T> List<T> mergeThree(Stream<List<T>> listStream) {
    return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
        l1.addAll(l2);
        return l1;
    });
}

private <T> List<T> mergeFour(Stream<List<T>> listStream) {
    return listStream.reduce((l1, l2) -> {
        List<T> l = new ArrayList<>(l1);
        l.addAll(l2);
        return l;
    }).orElse(new ArrayList<>());
}

private <T> List<T> mergeFive(Stream<List<T>> listStream) {
    return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}

将List<List>转换为List的方法:

listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());

请参见以下示例:

public class Example {

    public static void main(String[] args) {
        List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
        List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());

        System.out.println("listOfLists => " + listOfLists);
        System.out.println("list => " + list);
    }

}       

它打印:

listOfLists => [[a, b, c]]
list => [a, b, c]

在Python中,这可以使用列表理解来完成。

list_of_lists = [['Roopa','Roopi','Tabu', 'Soudipta'],[180.0, 1231, 2112, 3112], [130], [158.2], [220.2]]

flatten = [val for sublist in list_of_lists for val in sublist]

print(flatten)
['Roopa', 'Roopi', 'Tabu', 'Soudipta', 180.0, 1231, 2112, 3112, 130, 158.2, 220.2]