Reputation: 41
I have this code :
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");
}
}
}
And as you may see I want to sort a point Array, therefore I wrote (nearly) a comparable :
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;
}
}
What do I need to write inside the if()
clause?
Edit: From the comments
The condition would be that I look after the value of the distance between the point(0,0) and Point (x,y) (If this is even possible
Upvotes: 4
Views: 2806
Reputation: 10127
I would vote against your approach with creating a subclass
MyPoint extends Point implements Comparable<Point>
.
Instead I suggest to use the Array.sort(T[], Comparator<T>)
method
with a taylor-made Comparator<Point>
.
When using Java 8 you can write it very concisely like this:
Point[] pointArray = generatePointArray(15);
Arrays.sort(pointArray, Comparator.comparingDouble(p -> p.distance(0, 0)));
For Java 7 (and older) you need to use the more verbose syntax with an anonymous class:
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));
}
});
Upvotes: 0
Reputation: 6310
First calculate the distance from origin using a method in your class as:
Keep the precision value. Don't cast into INT, as it might be needed to compare the close points. For many points distance as integer values might be same.
private double distance(Point p) {
return (double) Math.sqrt(Math.pow(p.getX(), 2) + Math.pow(p.getY(), 2));
}
Then the compareTo method could be as follow.
Use compareTo method designed for wrapper classes.
public int compareTo(Object o) {
return new Double(distance(this)).compareTo(distance(Point(p)));
}
Upvotes: 0
Reputation: 31968
You can calculate the distance from origin using a private method in your class as:
private int distanceFromOrigin(Point point) {
return (int) Math.sqrt(Math.pow(point.getX(), 2) + Math.pow(point.getY(), 2));
}
Then the compareTo
method could be modified to include comparison between the distance of two Point
s as :
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;
}
Upvotes: 1
Reputation: 30839
You can compare x
and y
coordinates of both the points using lambda, e.g.:
Arrays.sort(points, (Point p1, Point p2) -> p1.getPx() == p2.getPx() ?
p1.getPy() - p2.getPy() : p1.getPx() - p2.getPx());
Update
Based on question edits, you can calculate the distance with Sqrt(x2 + y2)
formula and use it while comparing two points, e.g.:
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))));
Upvotes: 0
Reputation: 26926
It depends on how you would like to compare two points. The implementations differ if you:
There are potentially thousands of possible comparisons!
Here an example of code tha compare points by their distance to the origin (and in case the distance is equal comparing their position on x and y axis):
Note It is not necessary to calculate the real distance to check which point is closer to the origin. If you calculate the power of two of the distance you will get the same result using less cpu (so it is possible to remove the calculation of the square root). You are sure to obtain the same result because a distance is always a positive number. Additionaly using the expression x * x
is faster than using the expression Math.pow(x, 2)
. This optimization can be useful in this context because often geometric operations involve milions of points.
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;
}
}
Here a possible implementation that compare two points by x coordinates and if they are equals comparing y coordinates.
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;
}
}
Upvotes: 0
Reputation: 311823
Implementing the compareTo
method depends entirely on how you want to sort these points. One plausible way to do so is by their X and Y coordinates:
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());
}
}
Alternatively, instead of creating your own class that implements the Comparable
interface, you could use a custom Comparator
. With Java 8's enhancements, it would even be quite elegant:
Arrays.sort(
pointArray,
Comparator.comparing(Point::getX).thenComparing(Point::getY)
);
EDIT:
The comments added a suggestion to sort the points by their distance from the origin (0, 0). This is also easily doable with both mechanisms. The distance of a point from the origin is defined as sqrt(x*x + y*y)
. Since sqrt
is a monotonic transformation that does not affect the ordering, it can be omitted for a slight performance gain.
As 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());
}
}
With a custom Comparator
:
Arrays.sort(
pointArray,
Comparator.comparing(p -> (p.getX() * p.getX()) + (p.getY() * p.getY())
);
Upvotes: 4