Including elements from unmodified lists in modified lists in a 2D list with Streams

我们两清 提交于 2019-12-05 19:15:35

You have a problem with the parenthesis. Change this:

list.stream()
    .map(l -> Stream.concat(
            l.subList(0, l.size() - 1).stream().map(i -> i - 2),
            Stream.of(l.get(l.size() - 1)).collect(Collectors.toList())
    ))
    .collect(Collectors.toList());

To this:

list.stream()
    .map(l -> Stream.concat(
            l.subList(0, l.size() - 1).stream().map(i -> i - 2),
            Stream.of(l.get(l.size() - 1))).collect(Collectors.toList())
    )
    .collect(Collectors.toList());

Indentation is important here, to improve code readability. I would reindent the second snippet as follows:

list.stream()
    .map(l -> Stream.concat(
            l.subList(0, l.size() - 1).stream().map(i -> i - 2),
            Stream.of(l.get(l.size() - 1)))
        .collect(Collectors.toList()))
    .collect(Collectors.toList());

Or even better, I would move the logic that modifies the inner lists to a helper method:

public final class Utility {
    private Utility() { }

    public static List<Integer> modifyAllButLast(List<Integer> list) {
        return Stream.concat(
                l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                Stream.of(l.get(l.size() - 1)))
            .collect(Collectors.toList());
    }
}

And then I would just use this method from the outer stream:

list.stream()
    .map(Utility::modifyAllButLast)
    .collect(Collectors.toList());

Note: there's no need to move the helper method to a new Utility class and you might even let it be a non-static method. In this case, just change the Utility::modifyAllButLast method reference accordingly.

Let's fix the errors step by step

Stream#concat concats two streams together, but you concat one is a List<Integer> not a Stream<Integer>.

list.stream().map(l -> Stream.concat(
    l.subList(0, l.size() - 1).stream().map(i -> i - 2),
    Stream.of(l.get(l.size() - 1)).collect(Collectors.toList())
   // it returns List<Integer> ---^
)).collect(Collectors.toList());

THEN we can fix the error by return a Stream as below:

list.stream().map(l -> Stream.concat(
    l.subList(0, l.size() - 1).stream().map(i -> i - 2),
    Stream.of(l.get(l.size() - 1))
)).collect(Collectors.toList());

BUT the result is not as expected. we expected it returns a List<List<Integer>> but it returns a List<Stream<Integer>> instead. we can collecting the concatinated streams to List<Integer> as below:

list.stream().map(main -> 
    Stream.concat(
        main.subList(0, main.size() - 1).stream().map(i -> i - 2),
        Stream.of(main.get(main.size() - 1))           
    ).collect(Collectors.toList())
//   ^--- collecting Stream<Integer> to List<Integer>
).collect(Collectors.toList());

But I think the best way in this case is using List#replaceAll that I have answered in your another question which is more expressiveness and faster since Stream is more heavier than Collector.

list.stream().map(main ->
    main.stream().collect(collectingAndThen(toList(), it -> {
        // v--- replacing all items in list except the last one 
        it.subList(0, it.size() - 1).replaceAll(item -> item - 2);
        return it;
    }))
).collect(Collectors.toList());

This might not be the most elegant way to concatenate the two lists, but it will do it.

list.stream()
    .map(integerList -> {
        List<Integer> toReturn = integerList
                .subList(0, integerList.size() - 1)
                .stream()
                .map(i -> i - 2)
                .collect(Collectors.toList());
        toReturn.add(integerList.get(integerList.size() - 1));
        return toReturn;
    })
    .collect(Collectors.toList());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!