三角形多边形的数组vertices
包含3x Vector3D
个实例。方法应该在三角形的轴(x,y或z)上找到极值(最小值/最大值)。
E.g。三角形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
)以及如何减少我实施的整体复杂性?
答案 0 :(得分:1)
我会先使用mapToInt(ToIntFunction<? super T> 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中并对其执行Stream操作:
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();
答案 1 :(得分:1)
通过让调用者同时选择比较器(在本例中为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表达式提供内联reducer和mappers:
new Triangle().getExtremeValueForAxis(v -> v.getY(),
(n1, n2) -> n1 > n2 ? n2 : n1); //min by axis 0