我有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;
}

最佳答案

您正在执行的操作称为Mutable reduction

Pshemo’s answer显示了如何通过提供三个必要的功能来临时实现这种操作。但是,当所有三个功能由专用类实现时,在实现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);

09-05 20:02
查看更多