Strip Separator Elements

Is there a good way to use Java threads to alternate elements in a thread 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 saw many examples of how to join strings in a similar way, but did not find solutions for shared lists.

+7
java java-8 java-stream
source share
2 answers

You can do this with flatMap, but after the last element you will get an extra separator:

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

Here's another way, without a trailing separator:

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

This time we add a separator in front of each source element and get rid of the leading separator.

+8
source share

You can do a similar thing that Collectors.joining does with String 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 similarly to Collectors.joining(delimiter) :

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

produces

[1, 0, 2, 0, 3]

Please note that this is thread safe because of the collect method that protects these operations.


If you do not want to list, but insert delimiters as an intermediate stream, you can do this as follows:

 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 */ 
+6
source share

All Articles