具有重复值的Java Comparator排序顺序

时间:2016-02-19 04:41:59

标签: java

我对这段代码感到困惑,我的主要目标是,如果order.name' s相同,我想排序,其他方面-1或+1对我来说没问题。

预期结果:

 "abc"   "abc"   "def"   "ghi"   "ijk"

但该计划正在做一些不同的事情。我在这里错过了什么。

`import java.util.*;
public class Test1 {

    public static void main(String a[]) {

        List<Order> list = new ArrayList<Order>();

        list.add(new Order(10, "abc"));
        list.add(new Order(20, "def"));
        list.add(new Order(10, "abc"));
        list.add(new Order(40, "ghi"));
        list.add(new Order(50, "ijk"));

        Collections.sort(list, new CustComparator());

        System.out.println(" For Loop Results");
        for (Order object : list) {
            System.out.println(((Order) object).getName());
        }

    }

    static class CustComparator implements Comparator<Order> {

        @Override
        public int compare(Order o1, Order o2) {
            if (o1.getName().equals(o2.getName())) {
                System.out.println(" This line of code is not executing ");
                return 0;
            } else {
                System.out.println(" This line of code is executing ");
                return -1;
            }

        }

    }

    static class Order {

        public Order() {
        }

        public Order(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        private int id;
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Order other = (Order) obj;
            /*
             * if (id != other.id) return false;
             */
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    }
}`

并且程序输出是这样的:

This line of code is executing    
 This line of code is executing   
 This line of code is executing   
 This line of code is executing   

For Loop Results

ijk  
ghi  
abc  
def  
abc

谢谢大家,感谢您的所有回复,

最后我做了这样的事情,因为我正在寻找所有&#34; abc&#34;应该先在订单中显示。这是我的自定义比较器。

static class CustComparator implements Comparator<Order> {

    @Override
    public int compare(Order o1, Order o2) {

        int old=getModuleIndex(o1.getName());
        int new1 = getModuleIndex(o2.getName());
        if (old == new1) {
            return 0;
        } else if(old > new1){
            return 1;
        } else {
            return -1;
        }

    }
    int getModuleIndex(String obj) {
        if(obj.equals("abc")) {
            return 1;               
        } else {
            return 2;
        }
    }

}

4 个答案:

答案 0 :(得分:3)

原因是您的比较者违反了its contract.

  

实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))。

现在的方式,它只是在列表中运行,检查每对项目,并且,由于您实现它的方式,您的代码报告每个项目小于它之后的项目,并且所以sort确定不需要重新排序。它永远不会达到比较两个&#34; abc&#34; s。

的程度

如果您添加输出以查看o1o2(并实施toString方法),您可以查看传入的内容:

def_20 abc_10
 This line of code is executing 
abc_10 def_20
 This line of code is executing 
ghi_40 abc_10
 This line of code is executing 
ijk_50 ghi_40
 This line of code is executing

向您展示了这是正在发生的事情(注意第二和第三次比较使用第二个&#34; abc&#34;实例,而不是第一个)。

你可以通过正确实现比较器来解决这个问题,这样它就能知道第二个&#34; abc&#34;小于&#34; def&#34;。一个简单的解决方案是使用方法Bahramdun Adil mentions,然后执行o1.getName().compareTo(o2.getName())(当然使用正确的空值检查)。

答案 1 :(得分:1)

您可以这样做:编辑compare()方法

public int compare(Order o1, Order o2) {
    return o1.getName.compareTo(o2.getName);
}

注意:比较对象时,需要返回3个值:如果参数字符串等于此字符串,则返回0。如果此字符串小于字符串参数,则小于0的值。如果此字符串大于字符串参数,则值大于0.

答案 2 :(得分:1)

您的程序无法按预期运行的原因是因为您的compare方法违反了Javadoc

中所述的compare合同
  

实现者必须确保所有x和y的sgn(compare(x,y))== -sgn(compare(y,x))

如果x!= y违反此合同,则compare(x,y)compare(y,x)始终为-1。这就是排序不起作用的原因。

如何解决?在你的情况下,这很简单:只需实现compare corectly

@Override
public int compare(Order o1, Order o1) {
  return o1.getName().compareTo(o2.getName());
}

答案 3 :(得分:0)

其他答案解释了自定义比较器的问题。

我想补充一个事实,即您可以在不创建自己的比较器类的情况下实现所有目标。实际上,比较器接口中的方法甚至允许您按多个标准进行排序。

例如,如果要按名称排序,然后按id(对于具有相同名称的项目):

Collections.sort(list, Comparator.comparing(Order::getName).thenComparing(Order::getId));