切换到Java 8时的比较器问题

切换到Java 8时的比较器问题,java,sorting,java-8,comparator,java-6,Java,Sorting,Java 8,Comparator,Java 6,我正在从Java6迁移到Java8,并注意到Comparator接口的一些特殊之处。对此的任何见解都将非常有用 当我切换到Java8时,对象的顺序在“compare”方法中被切换,列表排序失败。我回到Java6,它工作得很好。这里有一个测试用例,我用Java8失败,用Java6通过 public class ComparitorTest { @Test public void comparatorTest(){ Record record1 = new Record("First",

我正在从Java6迁移到Java8,并注意到Comparator接口的一些特殊之处。对此的任何见解都将非常有用

当我切换到Java8时,对象的顺序在“compare”方法中被切换,列表排序失败。我回到Java6,它工作得很好。这里有一个测试用例,我用Java8失败,用Java6通过

public class ComparitorTest {

@Test
public void comparatorTest(){
    Record record1 = new Record("First", false);
    Record record2 = new Record("Second", true);
    List<Record> list = new ArrayList<Record>();

    list.add(record1);
    list.add(record2);


    final Comparator<Object> recordComparator = new Comparator<Object>()
            {
                public int compare( Object o1, Object o2 )
                {
                    Record r1 = (Record) o1;
                    Record r2 = (Record) o2;

                    Boolean isReadonly_R1 = r1.getIsReadOnly();
                    Boolean isReadOnly_R2 = r2.getIsReadOnly();

                if( isReadonly_R1.equals( Boolean.TRUE ) )
                    {
                        return 0;
                    }
                    else
                    {
                        return 1;
                    }
                }
            };
            Collections.sort(list, recordComparator);

            assertEquals(list.get(0).name, "Second");
            assertEquals(list.get(1).name, "First");

}



class Record {
    boolean isReadOnly; 
    String name;

    public Record(String name, boolean value) {
        isReadOnly =value;
        this.name = name;
    }

     boolean getIsReadOnly() {
        return isReadOnly;
    }
}   
公共类比较测试{
@试验
public void comparatorTest(){
记录1=新记录(“第一条”,假);
记录2=新记录(“第二条”,真);
列表=新的ArrayList();
列表。添加(记录1);
列表。添加(记录2);
最终比较器记录比较器=新比较器()
{
公共整数比较(对象o1、对象o2)
{
记录r1=(记录)o1;
记录r2=(记录)o2;
布尔值isReadonly_R1=R1.getIsReadOnly();
布尔值isReadOnly_R2=R2.getIsReadOnly();
if(isReadonly_R1.equals(Boolean.TRUE))
{
返回0;
}
其他的
{
返回1;
}
}
};
集合。排序(列表、记录比较器);
assertEquals(list.get(0).name,“Second”);
assertEquals(list.get(1.name),“First”);
}
课堂记录{
布尔值为只读;
字符串名;
公共记录(字符串名称,布尔值){
isReadOnly=值;
this.name=名称;
}
布尔getIsReadOnly(){
返回为只读;
}
}   
}


你们在这方面的任何见解都会非常有帮助

你们的比较仪完全崩溃了。如果说到目前为止一切顺利的话,那完全是因为运气

如果您确实比较(a,b)和
比较(b,a)
,则

  • a
    b
    相等,两个调用都返回0

  • a
    b
    不相等,一个呼叫返回正数,另一个呼叫返回负数

但是您的比较器从不返回负值。这打破了
compare
合同。您没有设置订单关系


另一个赠品提示是,您仅使用r1计算结果…

您的
比较器
不是有效的
比较器。它只查看要比较的第一项;它忽略了第二项。它不能返回负数,这意味着第一项不能被视为“小于”第二项

用于对列表进行排序的算法碰巧在Java6中工作(毕竟它有50/50的机会),但该算法必须在Java6和Java8之间进行更改

您需要根据以下内容修复
比较器的逻辑:

比较其两个参数的顺序。返回负整数、零或正整数,因为第一个参数小于、等于或大于第二个参数


此外,它不需要是
比较器。使它成为一个
比较器
比较
方法可以使用
记录
s而不是
对象
s。

补充现有答案,我将在Java 8中添加以下内容,您应该放弃整个自定义比较器实现。显然,您希望对记录进行排序,以便所有只读记录排在第一位,然后是所有可写记录。这是Java 8中的一行程序:

list.sort(Comparator.comparing(Record::getIsReadOnly).reverseOrder());

是的,算法改变了。在Java7中引入了TimSort。还有一个允许恢复到旧算法的系统属性,但由于修复损坏的比较器应该是首选,我不会浪费时间查找该属性的确切名称…