java—有没有办法只使用“map”而不使用“flatmap”将2d列表转换为1d列表?

t5zmwmid  于 2021-06-30  发布在  Java
关注(0)|答案(5)|浏览(452)

我是一个java初学者,我刚学会 map 以及 flatMap .
当2d列表应该转换为1d列表时,实现如下。

List<List<Integer>> list_2d = List.of(List.of(1, 2), List.of(3, 4));

List<Integer> lst1 = list_2d
    .stream()
    .flatMap(arr -> arr.stream())
    .collect(Collectors.toList());
printAll(lst1); // [1, 2, 3, 4]

但是,我认为它看起来可以不使用 flatMap .
有没有什么方法可以使代码具有相同的逻辑,仅仅使用 map ,不使用 flatMap ?
只是问因为如果 map 可以替换所有 flatMap ,没有理由背诵 flatMap . 我总是追求简单和基本的东西。

7d7tgy0s

7d7tgy0s1#

您可以迭代此2d列表,并将其中的元素(整数)添加到另一个1d列表:

List<List<Integer>> list_2d = List.of(List.of(1, 2), List.of(3, 4));

List<Integer> list_1d = new ArrayList<>();

IntStream.range(0, list_2d.size()).forEach(i ->
        IntStream.range(0, list_2d.get(i).size()).forEach(j ->
                list_1d.add(list_2d.get(i).get(j))));

System.out.println(list_1d); // [1, 2, 3, 4]
List<List<Integer>> list_2d = List.of(List.of(1, 2), List.of(3, 4));

List<Integer> list_1d = new ArrayList<>();

list_2d.forEach(list ->
        list.forEach(element ->
                list_1d.add(element)));

System.out.println(list_1d); // [1, 2, 3, 4]
3bygqnnd

3bygqnnd2#

由于已经有几个答案提供了不同的实现,我将尝试显示 map 以及 flatMap .
这个 map 操作用于将流中的每个元素更改为另一个元素。在您的示例中,可能的用例可以是在列表上进行一些聚合(例如。g。对所有元素求和),得出 List<Integer> 包含单个列表的所有总和。或者你可以改变数据结构,也许是一个集合,产生一个 List<Set<Integer>> . 结果列表中的元素数将始终为2,因为原始列表有2个元素。
这个 flatMap 另一方面,操作用于将一个元素转换为零个或多个元素。考虑一个由许多人组成的阶级家庭。如果你从某处得到一份家庭名单,但你只关心每个人,你可以 flatMap 从家族列表到人类列表。
两者的区别 flatMap 其他答案中给出的实现是操作类型: flatMap 是中间操作,意味着结果是 Stream . collect 以及 reduce 是终端操作,意味着结果是不同的(在您的示例中:a List<Integer> . 如果您想执行更多的流操作(例如。g。 filter 或者别的 map )你必须再创造一个 Stream 结果列表的。
为了说明这一点,考虑在你的问题中给出一个列表,因此你希望列表中的所有数字都是偶数。我用的是 collect 这个答案的答案。如你所见,使用 flatMap 保存不必要的列表创建以及一些代码行。

public static void usingFlatMap() {
    List<List<Integer>> originalList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));

    List<Integer> result = originalList
            .stream()
            .flatMap(list -> list.stream())
            .filter(number -> number % 2 == 0)
            .collect(Collectors.toList());

    System.out.println(result); // [2, 4]
}

public static void usingCollect() {
    List<List<Integer>> originalList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));

    List<Integer> intermediateList = originalList
            .stream()
            .collect(Collectors.flatMapping(List::stream, Collectors.toList()));
    List<Integer> result = intermediateList
            .stream()
            .filter(number -> number % 2 == 0)
            .collect(Collectors.toList());

    System.out.println(result); // [2, 4]
}
watbbzwu

watbbzwu3#

要回答这个问题,有其他的方法,但我不推荐任何我能想到的方法。例如,您可以使用reduction:

List<List<Integer>> list2d = List.of(List.of(1, 2), List.of(3, 4));

    List<Integer> lst1 = list2d
        .stream()
        .reduce((l1, l2) -> {
            ArrayList<Integer> concatenated = new ArrayList<>(l1);
            concatenated.addAll(l2);
            return concatenated;
        })
        .orElse(List.of()); // or else empty list

    System.out.println(lst1);

输出与您的相同:
[1, 2, 3, 4]
但是你的代码比我的代码更容易理解。我建议你坚持下去。

map()和flatmap()不能互换吗?

只是因为,如果Map可以取代所有的平面Map,就没有理由记住平面Map。我总是追求简单和基本的东西。
你已经得到了最简单最基本的东西。另外,为了充分利用流的潜力,您需要时不时地使用许多方法调用。在使用流多年之后,我仍然发现自己有时会在javadoc中查找它们。我得查一下 reduce() 为了这个答案。别指望什么都在你脑子里。我知道 flatMap() 不过,要记住这一点,因为它通常是实用的。
编辑:只是出于学术兴趣:通常你不能取代 flatMap()map() . 否则你会用 map() 从一开始。但反过来说:你总是可以取代 map()flatMap() . 你就是不想。例如,如果我们有:

List<String> strings = List.of("short", "somewhat longer");
    List<Integer> lengths = strings.stream()
            .map(String::length)
            .collect(Collectors.toList());
    System.out.println(lengths);

[5, 15]
如果因为某种奇怪的原因我们只记得 flatMap() ,不是 map() ,我们可以做:

List<Integer> lengths = strings.stream()
            .flatMap(s -> Stream.of(s.length()))
            .collect(Collectors.toList());

不过,我想很明显,它给我们带来的只是不必要的麻烦。最好记住这两件事 map() 以及 flatMap() 至少在我们需要的时候能查到。

ruyhziif

ruyhziif4#

可能这不是您想要的,但是如果目标是将所有子列表添加到一个结果列表中,那么使用for each也可能是一个简单和基本的选项:

List<List<Integer>> list_2d = List.of(List.of(1, 2), List.of(3, 4));
List<Integer> result = new ArrayList<>();
list_2d.forEach(list -> result.addAll(list));
System.out.println(result);
uxh89sit

uxh89sit5#

您可以删除 flatMap 如果在 collect :

List<Integer> lst1 = list_2d
    .stream()
    .collect(Collectors.flatMapping (List::stream, Collectors.toList()));

但是,我不认为使用 Collectors.flatMapping 而不是 flatMap .

相关问题