Collections.sort()在大型ArrayList中失败,经常排序 - java

我已经看到了很多与此问题相关的帖子,但是我进行的每张办公桌检查和实施的建议都无济于事。我不知道我是如何违反比较者的合同的。当然,我不经常使用比较器。

我有一个很大的ArrayList对象,它们在每次更新时都会排序,因为它们的位置经常变化。我必须按照从左下到右上的顺序渲染这些对象,以保持“深度”,就像2D程序一样。

这是我的比较器:

@Override
public int compare(RenderObject o1, RenderObject o2) 
{
    //if(o1 == null || o2 == null)
    //    return 0;

    if(o1 == null)
        return -1;
    else if(o2 == null)
        return 1;

    //vertices in order top-left, top-right, bottom-right, bottom-left
    PointF[]    bounds1 = o1.getVertices(),
                bounds2 = o2.getVertices();

    //if(bounds1 == null || bounds2 == null || bounds1.equals(bounds2))
    //  return 0;

    if(bounds1 == null)
        return -1;
    else if(bounds2 == null)
        return 1;

    if(bounds1[0].x >= bounds2[1].x || bounds1[3].y <= bounds2[0].y)
        return 1;
    else if(bounds1[1].x <= bounds2[0].x || bounds1[0].y >= bounds2[3].y)
        return -1;

    return o1.getZOrder() < o2.getZOrder() ? 1 : (o1.getZOrder() > o2.getZOrder() ? -1 : 0);
}

有人可以解释违反合同的地方吗?我尝试对o1和o2使用完全相同的顶点进行桌面检查,但无法弄清楚它们不相等。如果无法解决这个问题,我想我将不得不手动执行排序,这可能会更有效率,因为并非所有对象都会移动每次更新,但是我仍然想修复此代码,以备将来参考。

编辑:这是实际的错误,但正是其他所有人都因此问题而停止的地方。

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeForceCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
at ....Map.update(Map.java:237)
at ....GameMain.update(GameMain.java:76)
at ....BasicGame.start(BasicGame.java:173)
at ....GameMain.main(GameMain.java:121)

参考方案

您必须处理null吗?因为那可能是个问题。

现在,当涉及到null时,您将返回“等于”。

所以1 <2,并且1 == null,因此null应该小于2,但是在这里也相等。

要解决此问题,可以在null上出错(如果可以的话,则需要避免使用空值),或者将null设置为最小。

if (a == b) return 0;
if (a == null) return -1;
if (b == null) return 1;

同样,如果您执行>=,则不能返回1-1。可能相等,对吧?特别是,将对象与其自身(或自身的克隆)进行比较必须返回0。对于单元测试来说,这似乎是一个很好的案例。

Java-固定大小的列表与指定初始容量的列表之间的差异 - java

我在理解这一点上遇到了问题。当我们做 List<Integer> list = Arrays.asList(array); 我们不能在该列表上使用添加,删除之类的方法。我知道Arrays.asList()返回固定大小的列表。我不明白的是,如果我们创建一个具有指定初始容量的列表,例如List<Integer> list2 = new A…

Google Collections-来自collections.filter的可修改迭代器? - java

从Collections2.filter返回的集合是不可修改的,其迭代器也是如此。是否有类似的东西可以返回我经过过滤的集合实时视图,但是具有可修改的迭代器?我需要在迭代器上使用remove()方法。谢谢。 参考方案 new ArrayList(Collections2.filter(...))怎么样?如果出于某种原因坚持使用过滤器。顺便说一句,Collect…

是否有任何数据结构可以避免重复,保留顺序和随机访问 - java

以前,我正在寻找具有以下特征的数据结构。避免重复迭代顺序将与插入顺序相同在Java中,我使用LinkHashSet,在Python中,我使用OrderedDict现在,除了2个要求之外,我还有一个附加要求能够通过索引进行随机访问,这意味着我可以通过data[123]访问有没有可用的数据结构?还是我需要退回使用List? List可以完全满足第二和第三要求,但…

合并两个HashTable并删除Java中的重复项 - java

我有两个带有<int,string>对的哈希表。现在它们每个都有重复的值,我想合并两个哈希表以给我不同的值。我怎样才能做到这一点!?谢谢编辑#1我正在从目录中读取文件内容。并将这些内容作为令牌存储在两个不同的哈希表中。现在,我需要将它们合并到单个哈希表中,这将为我提供两个表的不同值。 参考方案 您可以使用putAll的Hashtable方法合并两…

将对象列表转换为数组。获取ArrayStoreException - java

我确实有这样的一段代码:List<VersionedUserIdentifier> userIdentifiers = getUsersModule().getUsersIdentifiers(); if (userIdentifiers.isEmpty()) { LOG.info(No users to verify."); retu…