我有一个可以工作的代码,它接受一个集合,并根据某个距离应用一个过滤器。
例如,列表中的第二个点必须与第一个点至少相距1公里,并且这两个点之间的任何项都将被删除。输入已排序。
private List<Point> filterByMinimumDistance(List<Point> points, double minDistance) {
Point reference = points.get(0);
List<Point> filtered = new ArrayList<>();
filtered.add(reference);
for (Point point : points) {
double distance = getDistance(reference, point);
if (distance >= minDistance) {
reference = point;
filtered.add(point);
}
}
return filtered;
}
private double getDistance(Point p1, Point p2) {
double dx = p1.getX() - p2.getX();
double dy = p1.getY() - p2.getY();
return Math.sqrt(dx * dx + dy * dy);
}到目前为止,我还没有想出一个更花哨的流解决方案来取代它。任何帮助都将不胜感激。谢谢!
发布于 2017-09-06 00:20:16
你可以为这些点创建一个自定义的收集器:
private static Collector<Point, ?, List<Point>> customCollector(double minDistance) {
class Acc {
private Point reference = null;
private List<Point> filtered = new ArrayList<>();
void accumulate(Point elem) {
if (reference == null) {
reference = elem;
}
double distance = getDistance(reference, elem);
if (distance >= minDistance) {
reference = elem;
filtered.add(elem);
}
}
Acc combine(Acc other) {
throw new UnsupportedOperationException("Not for parallel");
}
List<Point> finisher() {
return filtered;
}
private double getDistance(Point p1, Point p2) {
double dx = p1.getX() - p2.getX();
double dy = p1.getY() - p2.getY();
return Math.sqrt(dx * dx + dy * dy);
}
}
return Collector.of(Acc::new, Acc::accumulate, Acc::combine, Acc::finisher);
}用法为:
points.stream().collect(customCollector(minDistance));此外,我可能不得不在这里对combiner进行更多的思考,因为我不太确定它是否可以像这样正确实现:
Acc combine(Acc other) {
filtered.addAll(other.filtered);
return this;
}https://stackoverflow.com/questions/46058274
复制相似问题