我使用以下算法对 8k 元素列表进行排序。
//sort by y coordinates using the topleft point of every contour's bounding box
Collections.sort(contourList, new Comparator<MatOfPoint>() {
@Override
public int compare(MatOfPoint o1, MatOfPoint o2) {
Rect rect1 = Imgproc.boundingRect(o1);
Rect rect2 = Imgproc.boundingRect(o2);
int result = Double.compare(rect1.tl().y, rect2.tl().y);
return result;
}
} );
//sort by x coordinates
Collections.sort(contourList, new Comparator<MatOfPoint>() {
@Override
public int compare(MatOfPoint o1, MatOfPoint o2) {
Rect rect1 = Imgproc.boundingRect(o1);
Rect rect2 = Imgproc.boundingRect(o2);
int result = 0;
double total = rect1.tl().y/rect2.tl().y;
if (total>=0.9 && total<=1.4 ){
result = Double.compare(rect1.tl().x, rect2.tl().x);
}
return result;
}
});
问题是,虽然按Y坐标排序(第一个比较器)不会产生任何问题(我不知道这是否只是运气问题),
按X坐标(第二个比较器)排序会提示此异常:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
.我修改了算法,添加了以下内容来打印调试信息:
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
log.debug("tot: {}; p1.x: {}, p1.y: {}; p2.x {}, p2.y {}",
df.format(total),
rect1.tl().x,
rect1.tl().y,
rect2.tl().x,
rect2.tl().y);
,这些是异常发生前的最后10个条目:
tot: 0,85; p1.x: 81.0, p1.y: 1415.0; p2.x 429.0, p2.y 1657.0
tot: 0,78; p1.x: 81.0, p1.y: 1415.0; p2.x 677.0, p2.y 1820.0
tot: 0,75; p1.x: 81.0, p1.y: 1415.0; p2.x 703.0, p2.y 1879.0
tot: 0,78; p1.x: 81.0, p1.y: 1415.0; p2.x 1010.0, p2.y 1820.0
tot: 0,83; p1.x: 81.0, p1.y: 1415.0; p2.x 1250.0, p2.y 1708.0
tot: 0,85; p1.x: 81.0, p1.y: 1415.0; p2.x 1260.0, p2.y 1657.0
tot: 0,76; p1.x: 81.0, p1.y: 1415.0; p2.x 1282.0, p2.y 1867.0
tot: 0,82; p1.x: 81.0, p1.y: 1415.0; p2.x 1282.0, p2.y 1736.0
tot: 0,86; p1.x: 81.0, p1.y: 1415.0; p2.x 1282.0, p2.y 1649.0
tot: 0,76; p1.x: 81.0, p1.y: 1415.0; p2.x 1507.0, p2.y 1864.0
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:777)
at java.util.TimSort.mergeAt(TimSort.java:514)
at java.util.TimSort.mergeCollapse(TimSort.java:441)
at java.util.TimSort.sort(TimSort.java:245)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1462)
at java.util.Collections.sort(Collections.java:175)
我从来没有遇到过这样的问题,有人能提供一个解释和解决方案,让这些算法变得可靠吗?
预先非常感谢你的努力
里卡尔多
编辑1:我添加了如下调试信息:
static Comparator<MatOfPoint> contourXComparator() {
return new Comparator<MatOfPoint>() {
@Override
public int compare(MatOfPoint o1, MatOfPoint o2) {
Rect rect1 = boundingRect(o1);
Rect rect2 = boundingRect(o2);
int result = 0;
double total = rect1.tl().y / rect2.tl().y;
/* debug purpose */
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
log.debug("tot: {}; p1.x: {}, p1.y: {}; p2.x {}, p2.y {}",
df.format(total),
rect1.tl().x,
rect1.tl().y,
rect2.tl().x,
rect2.tl().y);
/* endof debug purpose */
if (total >= 0.9 && total <= 1.4) {
result = Double.compare(rect1.tl().x, rect2.tl().x);
}
return result;
}
};
您一致地返回一个值进行比较。例如,如果您为两个A返回-1
这段代码的主要问题是,您引入了一个if块,这违反了比较,因为您可能有一组坐标,即使它们不相等,您也可以通过返回0来调用它们。
您可以先尝试排序,就像对 y 所做的那样,然后再过滤掉。
您的第二个比较器不是传递的。考虑三个要素
(x,y)表示它们的边界矩形的尺寸。
根据您的比较器a
如何使用Comparator对对象的ArrayList进行正确排序,然后将排序后的数组传递给自定义数组适配器? 我试过这样做: ArrayList的内容类: 比较器: 在OnCreate中设置适配器: ...因为我使用的是定制的ArrayAdapter,就像: 我需要如何修改此适配器以使其与其他适配器一起工作? 谢谢你的帮助。
问题内容: 我正在为我的通讯录应用程序实现排序功能。 我想排序一个。是一个包含四个字段的类:姓名,家庭电话,手机号码和地址。我想继续。 如何编写自定义排序功能来做到这一点? 问题答案: 这是有关订购对象的教程: Java教程-集合-对象排序 尽管我会举一些例子,但我还是建议你阅读它。 有多种排序方式。如果要定义自然的(默认)排序,则需要让实现。假设你想默认在上进行排序name,然后执行(为简单起见
我有以下清单: 这是我的比较器函数: 我正在尝试使用它排序如下: 我不明白为什么第一个NaN不在列表的末尾。 我对升序排序列表的预期输出是: 我对降序排序列表的预期输出是: 在升序排序和降序排序的情况下,我希望NaNs在最后。 我知道sortwith使我们能够编写自己的比较器。有人能帮我吗?
我需要测试的地方 有人能告诉我如何使用main中的getCompByName()按名称对ArrayList进行排序吗?我对比较器很陌生,对它们的用法很难理解。该方法返回一个比较器,所以我不确定这将如何实现。我知道我需要使用getCompByName()来排序,我只是不知道如何实现它。
我有一个用类填充的树集。我想让这些按其继承排序,否则,只按其名称的字母顺序(以创建一个恒定的顺序)。但是由于某种原因,如果添加的类的顺序不正确,就会导致类的顺序不正确。 这是我的比较器: 下面是一个测试失败的例子: 排序集的实际值: 我的期望更像是: 我在调试时确实注意到,并非每个项目都相互比较。
问题内容: 我想为汽车清单开发一个排序演示。我正在使用数据表显示汽车列表。现在实际上我想按汽车颜色对列表进行排序。这里不是按字母顺序排序的。我想使用我的自定义排序顺序,例如先是红色汽车,然后是蓝色,等等。 为此,我尝试使用,但它只允许按字母顺序排序。 因此,任何人都可以指导我实现使用该技术的方法,以便使排序变得更快。 问题答案: 我建议你为汽车颜色创建一个枚举,而不要使用字符串,并且枚举的自然顺序