Interleave elements in a stream with separator

谁说胖子不能爱 提交于 2020-06-22 13:46:11

问题


Is there a nice way to use Java streams to interleave elements in a stream with a separator of the same type?

// Expected result in is list: [1, 0, 2, 0, 3]
List<Integer> is = Stream.of(1, 2, 3).intersperse(0).collect(toList()); 

This is similar to the intersperse function in Haskell and other functional languages.

I have seen many examples of how to join strings in a similar way but have not found any solutions for general lists.


回答1:


You can do it with flatMap, but you'll get an additional separator after the last element :

List<Integer> is = IntStream.of(1, 2, 3)
                            .flatMap(i -> IntStream.of(i, 0))
                            .collect(toList());

Here's another way, without the trailing separator :

List<Integer> is = IntStream.of(1, 2, 3)
                            .flatMap(i -> IntStream.of(0, i))
                            .skip(1)
                            .collect(toList());

This time we add the separator before each original element, and get rid of the leading separator.




回答2:


You can do a similar thing which Collectors.joining does with Strings with a little helper method:

static <T> Collector<T,List<T>,List<T>> intersperse(T delim) {
    return Collector.of(ArrayList::new, (l,e)-> {
        if(!l.isEmpty()) l.add(delim);
        l.add(e);
    }, (l,l2)-> {
        if(!l.isEmpty()) l.add(delim);
        l.addAll(l2);
        return l;
    });

then you can use it similar to Collectors.joining(delimiter):

List<Integer> l=Stream.of(1, 2, 3).collect(intersperse(0));

produces

[1, 0, 2, 0, 3]

Note that this is thread safe due to the way collect guards these operations.


If you don’t want to collect into a list but insert the delimiters as an intermediate stream operation you can do it this way:

Integer delimiter=0;
Stream.of(1, 2, 3)/** or any other stream source */
      .map(Stream::of)
      .reduce((x,y)->Stream.concat(x, Stream.concat(Stream.of(delimiter), y)))
      .orElse(Stream.empty())
      /* arbitrary stream operations may follow */


来源:https://stackoverflow.com/questions/25624638/interleave-elements-in-a-stream-with-separator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!