2017-09-05 39 views
2

我有一个工作代码,需要一个集合并应用基于一定距离的过滤器。转换Java 7代码,按距离过滤集合到流

例如,列表中的第二个点必须至少与第一个点相距1KM,并且这两个点之间的任何项目都将被删除。 输入已经排序。

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

到目前为止,我还没有能够拿出一些用一个更好的流解决方案替代这个问题。任何帮助,将不胜感激。谢谢!

+2

为什么你想要这样做?仅仅因为它“更有魅力”......? – Michael

+0

@迈克尔不是因为这个,但它会提高我的技能。我只是试图在这里学习 – victorantunes

+0

语义暗示:列表中的第一点与其余点不同:它不应该是列表的一部分。作为单独的参数传入。 –

回答

2

那么你可以为这些点创建一个自定义收集:

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; 
} 
+1

这确实看起来很麻烦。尽管如此,我并不打算使用组合器,因为并行化将打破需要按顺序排列的约束条件。但谢谢你的答案!我不知道如何实现自定义的收藏家,但你确实指出了我在正确的方向 – victorantunes

+0

@victorantunes串行或并行不影响结果的顺序顺便说一句,我仍然会增加一个组合,一旦我做思考关于它 – Eugene

+0

“收集器”并不真正适合直接实施,而且您需要静态方法,这真是令人遗憾。 – Michael