一个三角形多边形有一个包含3xVector3D
实例的数组vertices
。方法应该在三角形的轴(x,y或z)上找到极值(min/max)。
例如,三角形A(0, 0, 3) B(1, 2, 3) C(2, 2, -4)
在z轴上的最小值为-4
。
当前的实现如下所示:
public class Triangle implements Iterable<Vector3D> {
private final Vector3D[] vertices;
private final double kEpsilon = 1e-8;
public Triangle(Vector3D... vertices) {
Preconditions.checkArgument(vertices.length == 3);
this.vertices = vertices;
}
public double getExtremeValueForAxis(int axis) {
var minimum = getValueByAxisIndex(Arrays.stream(vertices).min((v, vOther) -> {
var vValueOnAxis = getValueByAxisIndex(v, axis);
var vOtherValueOnAxis = getValueByAxisIndex(vOther, axis);
return Double.compare(vValueOnAxis, vOtherValueOnAxis);
}).get(), axis);
return minimum;
}
private static double getValueByAxisIndex(final Vector3D vertex, final int axis) {
switch(axis) {
case 0: return vertex.getX();
case 1: return vertex.getY();
case 2: return vertex.getZ();
default: throw new IllegalArgumentException("Axis needs to be in 3D space!");
}
}
}
如何使用户能够通过传递函数Optional<T> min(Comparator<? super T> comparator);
或Optional<T> max(Comparator<? super T> comparator);
来搜索最小/最大值以避免布尔型标志(例如boolean searchForMin
),以及如何降低实现的整体复杂性?
发布于 2018-06-03 02:56:47
通过让调用者使用函数同时选择比较器(在本例中为reducer)和轴,可以真正简化函数及其调用:
/** valueFunction selects the axis
reducer selects which of 2 values to retain (max/min in this case)*/
public double getExtremeValueForAxis(
Function<Vector3D, Double> valueFunction, BinaryOperator<Double> reducer) {
return Arrays.stream(vertices)
.map(valueFunction)
.reduce(reducer)
.get();
}
然后,可以像这样简单地调用它:
new Triangle().getExtremeValueForAxis(Vector3D::getX, Math::max); //max by axis 0
new Triangle().getExtremeValueForAxis(Vector3D::getY, Math::min); //min by axis 1
当然,也可以使用lambda表达式提供内联缩减程序和映射器:
new Triangle().getExtremeValueForAxis(v -> v.getY(),
(n1, n2) -> n1 > n2 ? n2 : n1); //min by axis 0
发布于 2018-06-03 02:18:42
我将首先使用mapToInt(ToIntFunction mapper)
将流中的项映射到int
,然后使用min()
方法获取最小值。此方法不需要参数,因为它使用IntStream
,并且直接比较整数。
int minX = Arrays.stream(vertices).mapToInt(Vector3D::getX).min().getAsInt();
int minY = Arrays.stream(vertices).mapToInt(Vector3D::getY).min().getAsInt();
int minZ = Arrays.stream(vertices).mapToInt(Vector3D::getZ).min().getAsInt();
int min = Arrays.asList(minX, minY, minZ).stream().mapToInt(i -> i).min().getAsInt();
或者,将所有值连接到一个列表中,并对其执行流操作:
List<Integer> integers = new ArrayList<>();
Arrays.stream(vertices).forEach(i -> {
integers.add(i.getX()); integers.add(i.getY()); integers.add(i.getZ());
});
int min = integers.stream().mapToInt(i -> i).min().getAsInt();
https://stackoverflow.com/questions/50659699
复制相似问题