使用流通过自定义比较器收集到 TreeSet 中

2022-08-31 09:44:37

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

这工作正常。

现在我想从 where 中删除比某个值更旧的条目。但是我无法找出正确的Java 8语法来表达这一点。TreeSet positionReportstimestamp

这个尝试实际上编译了,但给了我一个带有未定义比较器的新比较器:TreeSet

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

我如何表达,我想收集到一个与比较器这样的?TreeSetComparator.comparingLong(PositionReport::getTimestamp)

我会想这样的事情

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

但这不会编译/似乎是方法引用的有效语法。


答案 1

当您的方法(或构造函数)适合您尝试满足的目标的形状时,可以使用方法引用。在这种情况下,不能使用方法引用,因为要定位的形状是 ,它不需要参数,但是您拥有的是一个构造函数,它确实需要一个参数,并且您需要指定该参数是什么。因此,您必须采用不太简洁的方法并使用 lambda 表达式:SupplierTreeSet

TreeSet<Report> toTreeSet(Collection<Report> reports, long timestamp) {
    return reports.stream().filter(report -> report.timestamp() >= timestamp).collect(
        Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparingLong(Report::timestamp))
        )
    );
}

答案 2

这很容易,只需使用下一个代码:

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