簡體   English   中英

如何使用Java 8流獲取路徑長度

[英]How to get length of path using java 8 streams

我有List<Vector3D> ,其中Vector3D是一個坐標。 我想找到列表的Vector3D元素之間所有距離的總和。 我想使用Java 8流找到它。 我嘗試使用reduce但不能幫助我。

UPD:

Vector3D類具有方法double distance(Vector3D)查找兩個位置之間的距離。 例如我有(1,0,0)(2,0,0)(3,0,0)的列表。 結果,我想找到這條路徑的長度。 是3

如果使用的是Java 7或更低版​​本,則必須執行以下操作:

public static double calcPathLength(List<Vector3D> path){
    double length = 0d;
    for (int i=0; i< path.size()-1; i++){
        length += path.get(i).distance(path.get(i+1));
    }
    return length;
}

您正在執行的操作稱為“ 可變約簡”

Pshemo的答案顯示了如何通過提供三個必要的功能來臨時實現這種操作。 但是,當所有三個功能都由專用類實現時,在實現Collector的類中實現這些功能可能Collector ,以便於重用:

public class Distance implements Collector<Vector3D, Distance.Helper, Double> {

    public static final Distance COLLECTOR = new Distance();

    static final class Helper {
        private double sum = 0;
        private Vector3D first = null, previous = null;
    }
    public Set<Characteristics> characteristics() {
        return Collections.emptySet();
    }
    public Supplier<Helper> supplier() {
        return Helper::new;
    }
    public BiConsumer<Helper, Vector3D> accumulator() {
        return (helper,vector3d)-> {
            if (helper.previous != null)
                helper.sum += vector3d.distance(helper.previous);
            else helper.first = vector3d;
            helper.previous = vector3d;
        };
    }
    public BinaryOperator<Helper> combiner() {
        return (h1,h2)-> {
            h2.sum += h1.sum;
            if(h1.previous!=null && h2.first!=null) {
                h2.sum += h1.previous.distance(h2.first);
                h2.first=h1.first;
            }
            return h2;
        };
    }
    public Function<Helper, Double> finisher() {
        return helper -> helper.sum;
    }
}

您將從臨時版本中識別出這三個功能。 New是第四個功能, finisher ,它允許指定如何從可變容器中提取最終結果,因此我們不需要getSum()調用。

用例可簡化為:

List<Vector3D> list;
//…
double distance=list.stream().collect(Distance.COLLECTOR);

選項之一是創建一些幫助程序類,該類將記住以前使用的向量,並基於該向量來計算它與當前向量之間的差。 這個課看起來像

class DistanceHelper {
    private double sum = 0;
    private Vector3D first = null;
    private Vector3D last = null;

    public void add(Vector3D vector3d) {
        if (first == null)
            first = vector3d;
        if (last != null)
            sum += vector3d.distance(last);
        last = vector3d;
    }

    public void combine(DistanceHelper otherHelper) {
        //add distance of path from current thread with distance of path
        //from other thread
        sum += otherHelper.sum;
        //also add distance between paths handled by separate threads like
        // when path of Thread1 is A->B and Thread2 is C->D then we need to 
        // include path from `B` to `C`
        if (this.last!=null && otherHelper.first!=null)
            sum += this.last.distance(otherHelper.first);
        this.last = otherHelper.last;
    }

    public double getSum() {
        return sum;
    }
}

您可以將其與例如combine一起使用,而不是像reduce這樣

double sum = list
        .stream()//or parallelStream()
        .collect(DistanceHelper::new, DistanceHelper::add,
                DistanceHelper::combine).getSum();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM