2017-09-05 24 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