Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to convert a 2D List to 1D List using only `map` not using `flatMap`?

I'm a Java beginner, I just got learn about map and flatMap.

When 2d List should be converted to 1d List, it was implemented like below.

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]

But, I think it looks that it can be implemented not using flatMap.

Are there any way to make the code with same logic, just using map, not using flatMap?

Just asking because if map can replace all of flatMap, there is no reason to memorize flatMap. I always pursue simple and basic things.

like image 377
frhyme Avatar asked Dec 20 '20 10:12

frhyme


1 Answers

To answer the question as asked, there are other ways, but I wouldn’t recommend any that I can think of. For example you may use 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);

Output is the same as yours:

[1, 2, 3, 4]

But your code is much easier to understand than mine. I suggest you stick to it.

Can’t map() and flatMap() be interchanged?

Just because, if map can replaced all of flatMap, there are no reason to memorize flatMap. I always pursue simple and basic thing.

You already got the simplest and most basic thing there is. Also to get the full potential from streams, there are many method calls that you will need to use now and then. After having used streams for years, I still find myself looking them up in the Javadoc sometimes. I had to look up the details of reduce() for this answer. Don’t expect to have everything in your head. I do know flatMap() by heart, though, since it is often practical.

Edit: Only out of academic interest: Typically you can’t replace flatMap() with map(). Or you would have used map() from the outset. But the other way around: You can always replace map() with flatMap(). You just wouldn’t want to. For example, if we had:

    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]

If for some strange reason we could only remember flatMap(), not map(), we could do:

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

I think it’s clear to see that all it brings us is needless complication, though. It’s better to remember both of map() and flatMap() at least well enough to be able to look them up when we need them.

like image 81
Ole V.V. Avatar answered Nov 01 '22 15:11

Ole V.V.