如何在Java中使用Comparator进行排序

Dan*_*Dan 163 java sorting comparator

我学会了如何使用比较器,但我对比较器有困难.我的代码中有错误:

Exception in thread "main" java.lang.ClassCastException: New.People cannot be cast to java.lang.Comparable
 at java.util.Arrays.mergeSort(Unknown Source)
 at java.util.Arrays.sort(Unknown Source)
 at java.util.Collections.sort(Unknown Source)
 at New.TestPeople.main(TestPeople.java:18)
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

import java.util.Comparator;

public class People implements Comparator {
   private int id;
   private String info;
   private double price;

   public People(int newid, String newinfo, double newprice) {
       setid(newid);
       setinfo(newinfo);
       setprice(newprice);
   }

   public int getid() {
       return id;
   }

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

   public String getinfo() {
       return info;
   }

   public void setinfo(String info) {
       this.info = info;
   }

   public double getprice() {
       return price;
   }

   public void setprice(double price) {
       this.price = price;
   }

   public int compare(Object obj1, Object obj2) {
       Integer p1 = ((People) obj1).getid();
       Integer p2 = ((People) obj2).getid();

       if (p1 > p2) {
           return 1;
       } else if (p1 < p2){
           return -1;
       } else {
           return 0;
       }
    }
}
Run Code Online (Sandbox Code Playgroud)
import java.util.ArrayList;
import java.util.Collections;

public class TestPeople {
    public static void main(String[] args) {
        ArrayList peps = new ArrayList();

        peps.add(new People(123, "M", 14.25));
        peps.add(new People(234, "M", 6.21));
        peps.add(new People(362, "F", 9.23));
        peps.add(new People(111, "M", 65.99));
        peps.add(new People(535, "F", 9.23));

        Collections.sort(peps);

        for (int i = 0; i < peps.size(); i++){
            System.out.println(peps.get(i));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信它必须在比较方法中对铸造做一些事情,但我正在玩它仍然无法找到解决方案

Bar*_*ers 207

你的示例类有几个尴尬的事情:

  • 它被称为人,而它有一个priceinfo(更多的东西对象,而不是人);
  • 当将一个类命名为复数时,它表明它是一个不止一件事的抽象.

无论如何,这是一个如何使用的演示Comparator<T>:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, new LexicographicComparator());
        System.out.println(people);
        Collections.sort(people, new AgeComparator());
        System.out.println(people);
    }
}

class LexicographicComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.name.compareToIgnoreCase(b.name);
    }
}

class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person a, Person b) {
        return a.age < b.age ? -1 : a.age == b.age ? 0 : 1;
    }
}

class Person {

    String name;
    int age;

    Person(String n, int a) {
        name = n;
        age = a;
    }

    @Override
    public String toString() {
        return String.format("{name=%s, age=%d}", name, age);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

等效的Java 8演示如下所示:

public class ComparatorDemo {

    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Joe", 24),
                new Person("Pete", 18),
                new Person("Chris", 21)
        );
        Collections.sort(people, (a, b) -> a.name.compareToIgnoreCase(b.name));
        System.out.println(people);
        Collections.sort(people, (a, b) -> a.age < b.age ? -1 : a.age == b.age ? 0 : 1);
        System.out.println(people);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Esko:比较减法"技巧"被破坏了一般`int` http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction/ (13认同)
  • AgeComparator和类似的整数比较可以简化为返回`a.age - b.age` (8认同)
  • @saikiran,你可以.但是当实现`Comparable`时,你必须选择一个属性进行比较.在一个人的情况下,有许多属性可以比较:年龄,长度,性别,名称等.在这种情况下,很容易提供几个执行这些比较的比较器. (3认同)

and*_*per 150

这是一个超短的模板,可以立即进行排序:

Collections.sort(people,new Comparator<Person>(){
   @Override
   public int compare(final Person lhs,Person rhs) {
     //TODO return 1 if rhs should be before lhs 
     //     return -1 if lhs should be before rhs
     //     return 0 otherwise (meaning the order stays the same)
     }
 });
Run Code Online (Sandbox Code Playgroud)

如果难以记住,请尽量记住它与类似的符号(就数字的符号而言):

 lhs-rhs 
Run Code Online (Sandbox Code Playgroud)

如果你想按升序排序:从最小的数字到最大的数字.

  • 我只是想知道1,-1,0的返回值是什么:O (10认同)
  • @ 40Plot,用于定位,用它们画一个标尺或轴. (3认同)

pol*_*nts 36

使用People implements Comparable<People>代替; 这定义了自然顺序People.

A Comparator<People>也可以另外定义,但People implements Comparator<People>不是正确的做事方式.

两个重载Collections.sort是不同的:

  • <T extends Comparable<? super T>> void sort(List<T> list)
    • 排序Comparable利用其自然排序的对象
  • <T> void sort(List<T> list, Comparator<? super T> c)
    • 使用兼容的方式排序 Comparator

你通过尝试排序来混淆两者Comparator(这也是为什么它没有意义Person implements Comparator<Person>).再次,要使用Collections.sort,您需要其中一个是真的:

  • 类型必须是Comparable(使用1-arg sort)
  • Comparator必须提供类型的A (使用2-args sort)

相关问题


另外,不要在新代码中使用原始类型.原始类型是不安全的,并且仅提供兼容性.

也就是说,而不是这个:

ArrayList peps = new ArrayList(); // BAD!!! No generic safety!
Run Code Online (Sandbox Code Playgroud)

你应该使用这样的类型安全泛型声明:

List<People> peps = new ArrayList<People>(); // GOOD!!!
Run Code Online (Sandbox Code Playgroud)

然后你会发现你的代码甚至没有编译!! 这将是一件好事,因为代码有问题(Person没有implements Comparable<Person>),但是因为你使用了原始类型,编译器没有检查这个,而是你ClassCastException在运行时得到了!!!

这应该说服您始终在新代码中使用类型安全泛型类型.总是.

也可以看看


Num*_*our 14

为了完整起见,这是一个简单的单线compare方法:

Collections.sort(people, new Comparator<Person>() {
    @Override
    public int compare(Person lhs, Person rhs) {  
        return Integer.signum(lhs.getId() - rhs.getId());  
    }
});
Run Code Online (Sandbox Code Playgroud)

  • 感谢使用`signum` (2认同)
  • @NumberFour " lhs.getId()-rhs.getId() " 不应该使用,它有整数溢出的变化。 (2认同)
  • `Integer.compare(lhs.getId(), rhs.getId());` 是一种更好的方法。正如@niraj.nijju 提到的,减法会导致溢出。 (2认同)

rin*_*nce 9

Java 8增加了一种制作Comparators的新方法,可以减少你必须编写的代码量,Comparator.comparing.另请查看Comparator.reversed

这是一个样本

import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import static org.junit.Assert.assertTrue;

public class ComparatorTest {

    @Test
    public void test() {
        List<Person> peopleList = new ArrayList<>();
        peopleList.add(new Person("A", 1000));
        peopleList.add(new Person("B", 1));
        peopleList.add(new Person("C", 50));
        peopleList.add(new Person("Z", 500));
        //sort by name, ascending
        peopleList.sort(Comparator.comparing(Person::getName));
        assertTrue(peopleList.get(0).getName().equals("A"));
        assertTrue(peopleList.get(peopleList.size() - 1).getName().equals("Z"));
        //sort by name, descending
        peopleList.sort(Comparator.comparing(Person::getName).reversed());
        assertTrue(peopleList.get(0).getName().equals("Z"));
        assertTrue(peopleList.get(peopleList.size() - 1).getName().equals("A"));
        //sort by age, ascending
        peopleList.sort(Comparator.comparing(Person::getAge));
        assertTrue(peopleList.get(0).getAge() == 1);
        assertTrue(peopleList.get(peopleList.size() - 1).getAge() == 1000);
        //sort by age, descending
        peopleList.sort(Comparator.comparing(Person::getAge).reversed());
        assertTrue(peopleList.get(0).getAge() == 1000);
        assertTrue(peopleList.get(peopleList.size() - 1).getAge() == 1);
    }

    class Person {

        String name;
        int age;

        Person(String n, int a) {
            name = n;
            age = a;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

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

        public void setAge(int age) {
            this.age = age;
        }
    }



}
Run Code Online (Sandbox Code Playgroud)


Ank*_*rma 6

为了完整性。

使用 Java8

people.sort(Comparator.comparingInt(People::getId));
Run Code Online (Sandbox Code Playgroud)

如果你想在 descending order

people.sort(Comparator.comparingInt(People::getId).reversed());
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

490877 次

最近记录:

5 年,9 月 前