我按自然顺序对点数组(使用自定义Point类)进行排序,并保存对点的引用。然后我使用比较器再次对它进行排序,并使用binarySearch找到相同的点(确保指定当前顺序)。这是在循环的上下文中完成的,而binarySearch每隔一次迭代就给出一个不正确的索引。为什么呢?
import java.util.Arrays;
public class TestSearch {
public static void main(String[] args) {
Point[] pts = new Point[6];
pts[0] = new Point(19000, 10000);
pts[1] = new Point(18000, 10000);
pts[2] = new Point(32000, 10000);
pts[3] = new Point(21000, 10000);
pts[4] = new Point(1234, 5678);
pts[5] = new Point(14000, 10000);
Arrays.sort(pts);
for (int i = 0; i < pts.length-2; i++) {
Point firstP = pts[i];
// Get a point from the array
Point secondP = pts[i+1];
System.out.println("The point I saved: " + secondP.toString());
// Find that same point and return it
// Why is this sometimes a different point?
Arrays.sort(pts, firstP.SLOPE_ORDER);
int secondI = Arrays.binarySearch(pts, secondP, firstP.SLOPE_ORDER);
System.out.println("The found point: " + pts[secondI].toString());
System.out.println("-----");
Arrays.sort(pts);
}
}
}
这是前两次迭代的输出。为什么它有时会返回与我搜索的点不同的点?
The point I saved: (14000, 10000) The found point: (14000, 10000) ----- The point I saved: (18000, 10000) The found point: (19000, 10000) -----
如果有帮助的话,那就是自定义Point类。
import java.util.Comparator;
public class Point implements Comparable<Point> {
// compare points by slope
public final Comparator<Point> SLOPE_ORDER = new BySlope();
private final int x; // x coordinate
private final int y; // y coordinate
// create the point (x, y)
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// slope between invoking point and end point
public double slopeTo(Point end) {
if (end == null)
throw new java.lang.NullPointerException("Point object is null");
if (this.equals(end))
return Double.NEGATIVE_INFINITY;
if (end.x - this.x == 0)
return Double.POSITIVE_INFINITY;
return (double) (end.y - this.y) / (double) (end.x - this.x);
}
// is invoking point lexicographically smaller than second one?
// comparing y-coordinates and breaking ties by x-coordinates
public int compareTo(Point second) {
if (this.y < second.y)
return -1;
if (this.y == second.y && this.x < second.x)
return -1;
if (this.y > second.y)
return 1;
if (this.y == second.y && this.x > second.x)
return 1;
return 0;
}
// return string representation of this point
public String toString() {
return "(" + x + ", " + y + ")";
}
private class BySlope implements Comparator<Point> {
@Override
public int compare(Point q1, Point q2) {
if (q1 == null || q2 == null)
throw new java.lang.NullPointerException("Point object"
+ "is null");
if (Point.this.slopeTo(q1) < Point.this.slopeTo(q2))
return -1;
if (Point.this.slopeTo(q1) > Point.this.slopeTo(q2))
return 1;
return 0;
}
}
}
答案 0 :(得分:0)
让我们把它剥掉一点。显然,第一个Arrays.sort
调用与问题无关:binarySearch
失败,只有在数组已经排序后才会调用。 “斜坡秩序”。
显然,问题在于你的Comparator
。 Comparator
本身没有任何问题,因为它看起来符合Comparator
Javadoc中建立的合同。但是,它与equals
不一致:可能有a
,b
,compare(a, b) == 0
,但a.equals(b) == false
。但是,由于二进制搜索只“看到”比较器建立的顺序,因此无法区分a
和b
,因此它可能会返回“看起来像”其中任何一个的第一个元素。
您的问题是您通过比较器定义这些点a
和b
等效,但仍然期望二进制搜索来区分它们并返回一个不仅等效的点,而且等于到您提供的点。尝试输出firstP.slopeTo(secondPt)
和firstP.slopeTo(pts[secondI])
- 这些值是否相等?
最后,一个解决方案是通过默认为Points的自然顺序来打破你的排序中的联系。也就是说,将return 0;
中的BySlope.compare
替换为return q1.compareTo(q2)
。