You can do it using the reduce() method with U
being another List<Slot>
, but it's a lot more convoluted than just doing it in a for
loop, unless parallel processing is required.
See end of answer for test setup.
Here is the for
loop implementation:
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]
Here is the stream reduce implementation:
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 results in an empty list, and the streams version results is a null
value.
Test Setup
All the above code used 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 slots
variable was 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 the result mixed
are printed using:
System.out.println(slots);
System.out.println(mixed);
Stream
s. This problem would almost certainly be better solved using a straightforward loop. – AntefixU
being anotherList<Slot>
, but it's be a bit more convoluted that just doing it in afor
loop, unless parallel processing is required. – Dextrad