You can do this using the reduce () method when U is another List<Slot> , but it is much more confusing than just doing it in a for loop if parallel processing is not required.
See end of answer for test setup.
Here is the implementation of the for loop:
List<Slot> mixed = new ArrayList<>(); Slot last = null; for (Slot slot : slots) if (last == null || last.end != slot.start) mixed.add(last = slot); else mixed.set(mixed.size() - 1, last = new Slot(last.start, slot.end));
Output
[3-5, 5-7, 8-10, 10-11, 11-13] [3-7, 8-13]
The following is a reduction in flow:
List<Slot> mixed = slots.stream().reduce((List<Slot>)null, (list, slot) -> { System.out.println("accumulator.apply(" + list + ", " + slot + ")"); if (list == null) { List<Slot> newList = new ArrayList<>(); newList.add(slot); return newList; } Slot last = list.get(list.size() - 1); if (last.end != slot.start) list.add(slot); else list.set(list.size() - 1, new Slot(last.start, slot.end)); return list; }, (list1, list2) -> { System.out.println("combiner.apply(" + list1 + ", " + list2 + ")"); if (list1 == null) return list2; if (list2 == null) return list1; Slot lastOf1 = list1.get(list1.size() - 1); Slot firstOf2 = list2.get(0); if (lastOf1.end != firstOf2.start) list1.addAll(list2); else { list1.set(list1.size() - 1, new Slot(lastOf1.start, firstOf2.end)); list1.addAll(list2.subList(1, list2.size())); } return list1; });
Output
accumulator.apply(null, 3-5) accumulator.apply([3-5], 5-7) accumulator.apply([3-7], 8-10) accumulator.apply([3-7, 8-10], 10-11) accumulator.apply([3-7, 8-11], 11-13) [3-5, 5-7, 8-10, 10-11, 11-13] [3-7, 8-13]
Changing it for parallel (multi-threaded) processing:
List<Slot> mixed = slots.stream().parallel().reduce(...
Output
accumulator.apply(null, 8-10) accumulator.apply(null, 3-5) accumulator.apply(null, 10-11) accumulator.apply(null, 11-13) combiner.apply([10-11], [11-13]) accumulator.apply(null, 5-7) combiner.apply([3-5], [5-7]) combiner.apply([8-10], [10-13]) combiner.apply([3-7], [8-13]) [3-5, 5-7, 8-10, 10-11, 11-13] [3-7, 8-13]
Caveat
If slots is an empty list, the for loop version outputs an empty list, and the stream version results are null .
Test setup
The above code uses the following Slot class:
class Slot { int start; int end; Slot(int start, int end) { this.start = start; this.end = end; } @Override public String toString() { return this.start + "-" + this.end; } }
The variable slots been defined as:
List<Slot> slots = Arrays.asList(new Slot(3, 5), new Slot(5, 7), new Slot(8, 10), new Slot(10, 11), new Slot(11, 13));
Both slots and mixed result are printed using:
System.out.println(slots); System.out.println(mixed);