2017-09-05 9 views
2

コレクションをとり、特定の距離に基づいてフィルタを適用する作業コードがあります。コレクションをストリームからストリームにフィルタリングするTransform Java 7コード

たとえば、リストの2番目のポイントは、最初のポイントから少なくとも1KM離れていなければなりません。また、その2つのポイントの間のアイテムはすべて削除されます。 入力はすでにソートされています。

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

@Michaelそれのためにではなく、それは私のスキルを向上させるでしょう。私はちょうどここで学ぶことを試みている – 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順次または並列は結果の順序に影響しません。 about it – Eugene

+0

Collectorは実際に直接実装されているわけではなく、静的メソッドが必要なことは残念です。 – Michael

関連する問題