使用比较器sorting – 降序(用户定义的类)
我想使用比较器以降序对我的对象进行sorting。
class Person { private int age; }
在这里我想sorting一个Person对象的数组。
我该怎么做?
您可以通过覆盖compare()方法来执行用户定义类的降序sorting,
Collections.sort(unsortedList,new Comparator<Person>() { @Override public int compare(Person a, Person b) { return b.getName().compareTo(a.getName()); } });
或者使用Collection.reverse()
按用户王子在评论中提到的降序sorting。
你可以这样做升序sorting
Collections.sort(unsortedList,new Comparator<Person>() { @Override public int compare(Person a, Person b) { return a.getName().compareTo(b.getName()); } });
用一个Lambdaexpression式(Java 8以上)replace上面的代码,我们得到了简洁:
Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));
从Java 8起,List具有以Comparator作为参数(更简洁)的sort()方法:
personList.sort((a,b)->b.getName().compareTo(a.getName()));
这里a
和b
被lambdaexpression式推断为Persontypes。
为什么它的价值在于我的标准答案。 这里唯一的新东西就是使用Collections.reverseOrder()。 另外它把所有的build议放在一个例子中:
/* ** Use the Collections API to sort a List for you. ** ** When your class has a "natural" sort order you can implement ** the Comparable interface. ** ** You can use an alternate sort order when you implement ** a Comparator for your class. */ import java.util.*; public class Person implements Comparable<Person> { String name; int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return name + " : " + age; } /* ** Implement the natural order for this class */ public int compareTo(Person p) { return getName().compareTo(p.getName()); } static class AgeComparator implements Comparator<Person> { public int compare(Person p1, Person p2) { int age1 = p1.getAge(); int age2 = p2.getAge(); if (age1 == age2) return 0; else if (age1 > age2) return 1; else return -1; } } public static void main(String[] args) { List<Person> people = new ArrayList<Person>(); people.add( new Person("Homer", 38) ); people.add( new Person("Marge", 35) ); people.add( new Person("Bart", 15) ); people.add( new Person("Lisa", 13) ); // Sort by natural order Collections.sort(people); System.out.println("Sort by Natural order"); System.out.println("\t" + people); // Sort by reverse natural order Collections.sort(people, Collections.reverseOrder()); System.out.println("Sort by reverse natural order"); System.out.println("\t" + people); // Use a Comparator to sort by age Collections.sort(people, new Person.AgeComparator()); System.out.println("Sort using Age Comparator"); System.out.println("\t" + people); // Use a Comparator to sort by descending age Collections.sort(people, Collections.reverseOrder(new Person.AgeComparator())); System.out.println("Sort using Reverse Age Comparator"); System.out.println("\t" + people); } }
String[] s = {"a", "x", "y"}; Arrays.sort(s, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); System.out.println(Arrays.toString(s)); -> [y, x, a]
现在你必须为Person类实现比较器。 类似于(升序): compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1
compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1
compare(Person a, Person b) = a.id < b.id ? -1 : (a.id == b.id) ? 0 : 1
或Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id))
。
为了最大限度地减less混淆,你应该实现一个升序比较器,并将其转换为一个包装( 像这样 ) new ReverseComparator<Person>(new PersonComparator())
。
我会为person类创build一个比较器,可以通过一定的sorting行为进行参数化。 在这里,我可以设置sorting顺序,但也可以修改,以允许sorting其他人的属性。
public class PersonComparator implements Comparator<Person> { public enum SortOrder {ASCENDING, DESCENDING} private SortOrder sortOrder; public PersonComparator(SortOrder sortOrder) { this.sortOrder = sortOrder; } @Override public int compare(Person person1, Person person2) { Integer age1 = person1.getAge(); Integer age2 = person2.getAge(); int compare = Math.signum(age1.compareTo(age2)); if (sortOrder == ASCENDING) { return compare; } else { return compare * (-1); } } }
(希望现在编译,我手头没有IDE或JDK,编码为“盲”)
编辑
感谢Thomas,编辑了代码。 我不会说Math.signum的使用是好的,高性能,有效的,但我想保持它作为一个提醒,compareTo方法可以返回任何整数,乘以(-1)将失败,如果实现返回Integer.MIN_INTEGER …我删除了setter,因为它足够便宜,只在需要的时候构造一个新的PersonComparator。
但我保持拳击,因为它表明我依赖现有的可比较的实现。 可以做类似Comparable<Integer> age1 = new Integer(person1.getAge());
但看起来太难看了 这个想法是显示一个模式,可以很容易地适应其他人的属性,如名称,生日,date等。
使用Google Collections:
class Person { private int age; public static Function<Person, Integer> GET_AGE = new Function<Person, Integer> { public Integer apply(Person p) { return p.age; } }; } public static void main(String[] args) { ArrayList<Person> people; // Populate the list... Collections.sort(people, Ordering.natural().onResultOf(Person.GET_AGE).reverse()); }
package com.test; import java.util.Arrays; public class Person implements Comparable { private int age; private Person(int age) { super(); this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int compareTo(Object o) { Person other = (Person)o; if (this == other) return 0; if (this.age < other.age) return 1; else if (this.age == other.age) return 0; else return -1; } public static void main(String[] args) { Person[] arr = new Person[4]; arr[0] = new Person(50); arr[1] = new Person(20); arr[2] = new Person(10); arr[3] = new Person(90); Arrays.sort(arr); for (int i=0; i < arr.length; i++ ) { System.out.println(arr[i].age); } } }
这是做这件事的一种方法。
java.util.Collection的类有一个sorting方法,它接受一个列表和一个自定义比较器 。 你可以定义你自己的比较器来sorting你的Person对象,只要你喜欢。