本文共 5848 字,大约阅读时间需要 19 分钟。
如何实现普通对象的排序,比如按某个属性的大小比较?
如何实现普通对象(自定义类的对象)的排序,比如按某个属性的大小比较?
Java中的对象,正常情况下,只能进行比较:== 或 != (== 操作是比较的对象的引用地址是否相同,如果使用equals方法,Object类中有equals方法内部就是使用了==,自定义类可以重写equals方法)。不能使用 > 或 < 的但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。
如何实现?Java中提供了两个接口: Comparable 或 Comparator
1.Java中的String类、包装类(Integer、Double、Short)等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。重写了compareTo()方法以后,就可以从小到大的排列
2. 重写compareTo(obj)的规则:
如果当前对象this大于形参对象obj,则返回正整数,
如果当前对象this小于形参对象obj,则返回负整数,
如果当前对象this等于形参对象obj,则返回零。
3. 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
由于String类实现了Comparable接口,实现了compareTo方法,所以可对String对象进行排序
//StringArray.javapackage com.ylaihui.comparable;import org.junit.Test;import java.util.Arrays;public class StringArray { @Test public void test1(){ String[] strs = new String[]{"yy","ll","aa","ii","hh","uu","ii"}; Arrays.sort(strs); System.out.println(Arrays.toString(strs)); // [aa, hh, ii, ii, ll, uu, yy] }}
通过之前对sort方法的分析,我们发现,要排序某个自定义类的对象,需要用到compareTo方法,该方法是在Comparable接口中的,所以要想实现自定义类的对象的排序,需要实现Comparable接口中的compareTo方法,否则会报 ClassCastException异常。
//Person.javapackage com.ylaihui.comparable;public class Person { String name; int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
//PersonSort.javapackage com.ylaihui.comparable;import java.util.Arrays;public class PersonSort { public static void main(String[] args) { Person[] people = new Person[4]; people[0] = new Person("yy",22); people[1] = new Person("ll",23); people[2] = new Person("aa",24); people[3] = new Person("ii",25); // ClassCastException: com.ylaihui.comparable.Person cannot be cast to java.lang.Comparable Arrays.sort(people); System.out.println(people); }}
对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
//Animal.javapackage com.ylaihui.comparable;public class Animal implements Comparable{ String name; int age; public Animal(String name, int age) { this.name = name; this.age = age; } public Animal() { } @Override public String toString() { return "Animal{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Object o) { if(o instanceof Animal){ Animal animal = (Animal)o; if(this.age > animal.age) return 1; else if(this.age < animal.age) return -1; else return 0; }else throw new RuntimeException("类型不一致,无法比较"); }}
//AnimalSort.javapackage com.ylaihui.comparable;import java.util.Arrays;public class AnimalSort { public static void main(String[] args) { Animal[] animals= new Animal[4]; animals[0] = new Animal("yy",22); animals[1] = new Animal("ll",23); animals[2] = new Animal("aa",24); animals[3] = new Animal("ii",25); Arrays.sort(animals); System.out.println("sort by age"); System.out.println(Arrays.toString(animals)); }}
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
//ComparatorTest.javapackage com.ylaihui.comparable;import java.util.Arrays;import java.util.Comparator;public class ComparatorTest { public static void main(String[] args) { Animal[] animals= new Animal[6]; animals[0] = new Animal("yy",22); animals[1] = new Animal("ll",23); animals[2] = new Animal("aa",24); animals[3] = new Animal("aa",27); animals[4] = new Animal("ii",28); animals[5] = new Animal("hh",28); // 创建了一个匿名子类的匿名对象 Arrays.sort(animals, new Comparator() { @Override // 按 age 从大到小排序 public int compare(Object o1, Object o2) { if(o1 instanceof Animal && o2 instanceof Animal){ Animal a1 = (Animal) o1; Animal a2 = (Animal) o2; return -(a1.age - a2.age); }else throw new RuntimeException("类型不一致,无法比较"); } }); System.out.println(Arrays.toString(animals)); }}
//ComparatorTest1.javapackage com.ylaihui.comparable;import java.util.Arrays;import java.util.Comparator;public class ComparatorTest1 { public static void main(String[] args) { Animal[] animals= new Animal[6]; animals[0] = new Animal("yy",23); animals[1] = new Animal("ll",23); animals[2] = new Animal("aa",24); animals[3] = new Animal("aa",27); animals[4] = new Animal("ii",28); animals[5] = new Animal("hh",28); Arrays.sort(animals, new Comparator() { @Override // 按 age 从大到小排序,age相同,按name从大到小排序 public int compare(Object o1, Object o2) { if(o1 instanceof Animal && o2 instanceof Animal){ Animal a1 = (Animal) o1; Animal a2 = (Animal) o2; if(a1.age == a2.age) return -a1.name.compareTo(a2.name); return -(a1.age - a2.age); }else throw new RuntimeException("类型不一致,无法比较"); } }); System.out.println(Arrays.toString(animals)); }}
Comparable接口的方式一旦确定,保证Comparable接口实现类的对象在任何位置都可以比较大小,可多次使用。自然排序
Comparator接口属于临时性的比较,只能使用一次。定制排序
转载地址:http://rtuhf.baihongyu.com/