Подтвердить что ты не робот

Использование потоков для сбора в TreeSet с помощью пользовательского компаратора

Работа в Java 8, у меня есть TreeSet, как это:

private TreeSet<PositionReport> positionReports = 
        new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp));

PositionReport - довольно простой класс, определенный следующим образом:

public static final class PositionReport implements Cloneable {
    private final long timestamp;
    private final Position position;

    public static PositionReport create(long timestamp, Position position) {
        return new PositionReport(timestamp, position);
    }

    private PositionReport(long timestamp, Position position) {
        this.timestamp = timestamp;
        this.position = position;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public Position getPosition() {
        return position;
    }
}

Это отлично работает.

Теперь я хочу удалить записи из TreeSet positionReports, где timestamp старше некоторого значения. Но я не могу понять правильный синтаксис Java 8, чтобы выразить это.

Эта попытка действительно компилируется, но дает мне новый TreeSet с компаратором undefined:

positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(Collectors.toCollection(TreeSet::new))

Как я могу выразить, что я хочу собрать в TreeSet со компаратором, например Comparator.comparingLong(PositionReport::getTimestamp)?

Я бы подумал что-то вроде

positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(
            Collectors.toCollection(
                TreeSet::TreeSet(Comparator.comparingLong(PositionReport::getTimestamp))
            )
        );

Но это не компилирует/не представляется сильным синтаксисом для ссылок на методы.

4b9b3361

Ответ 1

Comparator<PositionReport> byTimestamp =
    Comparator.comparingLong(PositionReport::getTimestamp);

Supplier<TreeSet<PositionReport>> supplier =
    () -> new TreeSet<PositionReport>(byTimestamp);

positionReports = positionReports.stream()
                                 .filter(p -> p.getTimeStamp() >= oldestKept)
                                 .collect(Collectors.toCollection(supplier));

Ответ 2

Вы можете просто преобразовать в SortedSet в конце (при условии, что вы не возражаете против дополнительной копии).

positionReports = positionReports
                .stream()
                .filter(p -> p.getTimeStamp() >= oldestKept)
                .collect(Collectors.toSet());

return new TreeSet(positionReports);

Ответ 3

Это легко просто использовать следующий код:

    positionReports = positionReports
        .stream()
        .filter(p -> p.timestamp >= oldestKept)
        .collect(
            Collectors.toCollection(()->new TreeSet<>(Comparator.comparingLong(PositionReport::getTimestamp)
)));

Ответ 4

Существует метод для Collection для этого без использования потоков: default boolean removeIf(Predicate<? super E> filter). См. Javadoc.

Итак, ваш код может выглядеть примерно так:

positionReports.removeIf(p -> p.timestamp < oldestKept);