Is there a way to let the 'reduction' of the reduce() method of Stream be optional?
I want to iterate over a list of Periods and join the periods that overlap and maintain both periods if they don't overlap:
interface Period {
boolean overlaps(Period other);
}
List<Period> periods = new ArrayList<>();
periods.stream().reduce(new BinaryOperator<Period>() {
@Override
public Period apply(Period period, Period period2) {
if (period.overlaps(period2)){
// join period and period2 into period.
}else{
"return both"
// don't reduce and maintain period and period2 in the list.
}
return null;
}
});
I don't think you can easily do it with streams alone. With Guava ranges, you can do something like this:
periods.stream()
.map(p -> Range.closedOpen(p.getStart(), p.getEnd()))
.collect(TreeRangeSet::<Integer>create, RangeSet::add, RangeSet::addAll)
.asRanges()
.stream()
.map(r -> new PeriodImpl(r.lowerEndpoint(), r.upperEndpoint()))
.collect(Collectors.toList());
This assumes a class structure like the following, but you can adjust as necessary:
interface Period {
int getStart();
int getEnd();
}
class PeriodImpl implements Period {
PeriodImpl(int start, int end) {
//...
}
//...
}
Try collapse
provided in StreamEx
// Here I use Range type provided in Google Guava for test.
List<Range<Integer>> list = Arrays.asList(Range.openClosed(1, 3), Range.openClosed(2, 4), Range.closed(5, 5));
StreamEx.of(list)
.collapse(Range::isConnected, Range::span)
.forEach(System.out::println);
// (1..4]
// [5..5]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With