为Arrays.Sort of Points写一个可比较的

时间:2017-09-18 16:09:21

标签: java arrays comparable points

我有这段代码:

import java.awt.Point;
import java.util.Arrays;

public class Haupt {

    // creates an array of anz Point objects
    public static Point[] generatePointArray(int anz) {
        Point[] pa = new Point[anz];
        for(int i = 0; i < anz; i++) {
            int px = (int) (Math.random() * 10);
            int py = (int) (Math.random() * 10);
            pa[i] = new Point(px,py);
        }
        return pa;
    }

    public static void main(String[] args) {
        Point[] pointArray = generatePointArray(15);

        Arrays.sort(pointArray);


        for(int i = 0 ;  i < pointArray.length; i++) {
            System.out.println("Point: "+pointArray[i] +
            " has distance "+pointArray[i].distance(0,0)+
            " from origin");
        }
    }
}

正如你可能看到我想要对一个点数组进行排序,因此我写了(几乎)一个可比的:

import java.awt.Point;

public class MyPoint extends Point implements Comparable {
    public int compareTo(Object o)
    {
        Point p = (Point) o;


        if () {
            return -1;
        }
        if () {
            return 1;
            }
        return 0;
    }

}

我需要在if()子句中写一下什么?

编辑:来自评论

  

条件是我会照看距离的值   点(0,0)和点(x,y)之间(如果这是可能的

6 个答案:

答案 0 :(得分:1)

您可以使用班级中的私人方法计算与原点的距离:

private int distanceFromOrigin(Point point) {
    return (int) Math.sqrt(Math.pow(point.getX(), 2) + Math.pow(point.getY(), 2));
}

然后可以修改compareTo方法以包括两个Point的距离之间的比较:

public int compareTo(Object o) {
    Point p = (Point) o;
    if (distanceFromOrigin(p) > distanceFromOrigin(this)) {
        return -1;
    }
    if (distanceFromOrigin(p) < distanceFromOrigin(this)) {
        return 1;
    }
    return 0;
}

答案 1 :(得分:0)

实施compareTo方法完全取决于您希望如何对这些点进行排序。一种合理的方法是通过它们的X和Y坐标:

public class MyPoint extends Point implements Comparable<MyPoint> {
    public int compareTo(MyPoint o) {
        int retVal = Double.compare(getX(), o.getX());
        if (retVal != 0) {
            return retVal;
        }
        return Double.compare(getY(), o.getY());
    }
}

或者,您可以使用自定义Comparator,而不是创建自己的实现Comparable接口的类。使用Java 8的增强功能,它甚至会非常优雅:

Arrays.sort(
    pointArray, 
    Comparator.comparing(Point::getX).thenComparing(Point::getY)
);

编辑:
评论添加了一个建议,即按点与原点(0,0)的距离对点进行排序。这两种机制也很容易实现。点与原点的距离定义为sqrt(x*x + y*y)。由于sqrt是一种不会影响排序的单调变换,因此可以省略它以获得轻微的性能提升。

作为Comparaable

public class MyPoint extends Point implements Comparable<MyPoint> {
    public int compareTo(MyPoint o) {
        return Long.compare(getCompareKey(), o.getCompareKey());
    }

    private long getCompareKey() {
        return (getX() * getX()) + (getY() * getY());
    }
}

使用自定义Comparator

Arrays.sort(
    pointArray, 
    Comparator.comparing(p -> (p.getX() * p.getX()) + (p.getY() * p.getY())
);

答案 2 :(得分:0)

这取决于你想要比较两点的方式。 如果您:

,实施会有所不同
  • 如果p1更接近原点(0,0)
  • ,则说p1在p2之前
  • 如果p1的x坐标在p2
  • 之前,则说p1在p2之前
  • 如果p1的x和y坐标之和高于p2,则p1在p2之前

可能存在数千种可能的比较!

这里是一个代码示例,通过它们与原点的距离来比较点(如果距离相等,则比较它们在x和y轴上的位置):

注意没有必要计算实际距离来检查哪个点更接近原点。如果计算两个距离的幂,您将使用较少的cpu得到相同的结果(因此可以删除平方根的计算)。您肯定会获得相同的结果,因为距离始终是正数。另外,使用表达式x * x比使用表达式Math.pow(x, 2)更快。这种优化在这种情况下很有用,因为几何操作通常涉及数百万个点。

 public class MyPoint extends Point implements Comparable {
    public int compareTo(Object o) {
        Point p = (Point) o;

        // Note that if sqr(x^2 + y^2) < sqr(p.x^2 + p.y*2) 
        // Also x^2 + y^2 < p.x*2 + p.y*2 but you save
        // computing cicles
        // THis is possible because we are comparing distances,
        // it is not necessary to calculate the right distance if
        // you need only to know the comparison between them
        if (x*x + y*y < p.x*p.x + p.y*p.y) {
           return -1;
        } else if (x*x + y*y > p.x*p.x + p.y*p.y) {
           return 1;
        } 

        // In case of same distance to origin compare x and subsequent y positions.

        if (x > p.x) {
            return -1;
        } else if (x < p.x) {
            return 1;
        } else if (y < p.y) {
            return 1;
        } else if (y > p.y) {
            return -1;
        }
        return 0;
     }
}

这里有一个可能的实现,它将两个点乘以x坐标,如果它们等于比较y坐标。

 public class MyPoint extends Point implements Comparable {
    public int compareTo(Object o) {
        Point p = (Point) o;

        if (x > p.x) {
            return -1;
        } else if (x < p.x) {
            return 1;
        } else if (y < p.y) {
            return 1;
        } else if (y > p.y) {
            return -1;
        }
        return 0;
     }
}

答案 3 :(得分:0)

您可以使用lambda比较两个点的xy坐标,例如:

Arrays.sort(points, (Point p1, Point p2) -> p1.getPx() == p2.getPx() ? 
        p1.getPy() - p2.getPy() : p1.getPx() - p2.getPx());

<强>更新

根据问题编辑,您可以使用Sqrt(x2 + y2)公式计算距离,并在比较两个点时使用它,例如:

Arrays.sort(points, (Point p1, Point p2) -> (int) Math.sqrt(Math.pow(p1.getPx(), 2) + 
        Math.pow(p1.getPy(), 2) - Math.sqrt(Math.pow(p2.getPx(), 2) + Math.pow(p2.getPy(), 2))));

答案 4 :(得分:0)

首先使用您班级中的方法计算距离原点的距离:

  

保持精确值。不要转换为INT,因为可能需要比较关闭点。对于许多点,距离作为整数值可能相同。

private double distance(Point p) {
    return (double) Math.sqrt(Math.pow(p.getX(), 2) + Math.pow(p.getY(), 2));
}

然后compareTo方法可以如下。

  

使用为包装类设计的compareTo方法。

public int compareTo(Object o) {

    return new Double(distance(this)).compareTo(distance(Point(p)));

}

答案 5 :(得分:0)

我会投票反对你创建子类的方法 MyPoint extends Point implements Comparable<Point>

相反,我建议使用Array.sort(T[], Comparator<T>)方法 用泰勒制作的Comparator<Point>

使用Java 8时,您可以非常简洁地编写它:

Point[] pointArray = generatePointArray(15);
Arrays.sort(pointArray, Comparator.comparingDouble(p -> p.distance(0, 0)));

对于Java 7(及更早版本),您需要使用更详细的语法 匿名课程:

Point[] pointArray = generatePointArray(15);
Arrays.sort(pointArray, new Comparator<Point>() {
    @Override
    public int compare(Point p1, Point p2) {
        return Double.compare(p1.distance(0, 0), p2.distance(0, 0));
    }
});