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

时间:2015-08-27 23:18:09

标签: java sorting java-8 comparator java-6

我正在从Java 6迁移到Java 8,并注意到Comparator接口特有的一些东西。对此的任何见解都会非常有帮助。

当我切换到Java 8时,对象的顺序在“compare”方法内切换,列表排序失败。我回到java 6,它工作得很好。这是一个测试用例,对于Java 8来说无法使用,并且使用了Java 6。

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;
    }
}   

}

你们对此有任何见解会非常有帮助

3 个答案:

答案 0 :(得分:10)

您的Comparator不是有效的Comparator。它只查看要比较的第一个项目;它忽略了第二项。它无法返回一个负数,这意味着第一个项目永远不会被认为是&#34;小于&#34;第二项。

用于对列表进行排序的算法恰好在Java 6中运行(毕竟它有50/50的机会),但算法必须在Java 6和Java 8之间进行更改。

您需要根据the compare method's contract修正Comparator的逻辑:

  

比较其订单的两个参数。当第一个参数小于,等于或大于第二个参数时,返回负整数,零或正整数。

此外,它不需要是Comparator<Object>。设为Comparator<Record>compare方法可以Record而不是Object

答案 1 :(得分:5)

你的比较器完全被打破了。如果它已经工作到现在,那是因为纯粹的运气。

如果您执行compare(a, b)compare(b,a),则

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

  • ab不相等,一次通话返回正数,另一次为负数。

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

另一个赠品提示是你只使用r1来计算结果......

答案 2 :(得分:2)

补充现有答案我将添加以下内容到Java 8,您应该删除整个自定义Comparator实现。显然,您希望对记录进行排序,以便所有只读记录首先出现,然后是所有可写记录。这是Java 8中的单行代码:

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