Применять сокращение только при соблюдении определенных условий - PullRequest
0 голосов
/ 04 декабря 2018

Есть ли способ разрешить 'уменьшение' метода Reduce () в Stream не обязательно?

Я хочу перебрать список периодов и объединить периоды, которые перекрываются, и поддерживать оба периода, если они не перекрываются:

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;
    }
});

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Попробуйте collapse в 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]
0 голосов
/ 04 декабря 2018

Я не думаю, что вы можете легко сделать это с помощью одних потоков.С диапазонами гуавы вы можете сделать что-то вроде этого:

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());

Это предполагает структуру класса, подобную приведенной ниже, но вы можете изменить ее при необходимости:

interface Period {
    int getStart();
    int getEnd();
}

class PeriodImpl implements Period {
    PeriodImpl(int start, int end) {
        //...
    }
    //...
}
...