首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java Lambda -查找包含Vector3D实例的三角形的极值的更好方法

Java Lambda -查找包含Vector3D实例的三角形的极值的更好方法
EN

Stack Overflow用户
提问于 2018-06-03 02:00:11
回答 2查看 78关注 0票数 1

一个三角形多边形有一个包含3xVector3D实例的数组vertices。方法应该在三角形的轴(x,y或z)上找到极值(min/max)。

例如,三角形A(0, 0, 3) B(1, 2, 3) C(2, 2, -4)在z轴上的最小值为-4

当前的实现如下所示:

代码语言:javascript
复制
   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),以及如何降低实现的整体复杂性?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-06-03 02:56:47

通过让调用者使用函数同时选择比较器(在本例中为reducer)和轴,可以真正简化函数及其调用:

代码语言:javascript
复制
/** 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();
}

然后,可以像这样简单地调用它:

代码语言:javascript
复制
new Triangle().getExtremeValueForAxis(Vector3D::getX, Math::max); //max by axis 0
new Triangle().getExtremeValueForAxis(Vector3D::getY, Math::min); //min by axis 1

当然,也可以使用lambda表达式提供内联缩减程序和映射器:

代码语言:javascript
复制
new Triangle().getExtremeValueForAxis(v -> v.getY(), 
            (n1, n2) -> n1 > n2 ? n2 : n1); //min by axis 0
票数 1
EN

Stack Overflow用户

发布于 2018-06-03 02:18:42

我将首先使用mapToInt(ToIntFunction mapper)将流中的项映射到int,然后使用min()方法获取最小值。此方法不需要参数,因为它使用IntStream,并且直接比较整数。

代码语言:javascript
复制
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();

或者,将所有值连接到一个列表中,并对其执行流操作:

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50659699

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档