Ordenação usando ordem de Comparador-Descendente (classs definidas pelo usuário)

Eu quero classificar meus objects em ordem decrescente usando o comparador.

class Person { private int age; } 

Aqui eu quero classificar uma matriz de objects Person.

Como posso fazer isso?

Você pode fazer a sorting descendente de uma class definida pelo usuário desta forma sobrescrevendo o método compare () ,

 Collections.sort(unsortedList,new Comparator() { @Override public int compare(Person a, Person b) { return b.getName().compareTo(a.getName()); } }); 

Ou usando Collection.reverse() para classificar descendente como usuário Prince mencionado em seu comentário .

E você pode fazer o tipo crescente assim,

 Collections.sort(unsortedList,new Comparator() { @Override public int compare(Person a, Person b) { return a.getName().compareTo(b.getName()); } }); 

Substitua o código acima por uma expressão do Lambda (Java 8 em diante).

 Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName())); 

A partir do Java 8, List possui o método sort () que toma o Comparator como parâmetro (mais conciso):

 personList.sort((a,b)->b.getName().compareTo(a.getName())); 

Aqui b são inferidos como tipo de pessoa pela expressão lambda.

Pois o que vale aqui é a minha resposta padrão. A única coisa nova aqui é que usa o Collections.reverseOrder (). Além disso, coloca todas as sugestões em um exemplo:

 /* ** 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 { 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 { 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 people = new ArrayList(); 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() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); System.out.println(Arrays.toString(s)); -> [y, x, a] 

Agora você precisa implementar o Comparador para sua class Person. Algo como (por ordem crescente): 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 ou Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)) .

Para minimizar a confusão, você deve implementar um Comparador ascendente e convertê-lo em um descendente com um wrapper ( como este ) new ReverseComparator(new PersonComparator()) .

Eu criaria um comparador para a class de pessoa que pode ser parametrizada com um certo comportamento de sorting. Aqui eu posso definir a ordem de sorting, mas ela também pode ser modificada para permitir a sorting de outros atributos de pessoa.

 public class PersonComparator implements Comparator { 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); } } } 

(espero que compile agora, eu não tenho IDE ou JDK à mão, codificado como “cego”)

Editar

Graças a Thomas, editei o código. Eu não diria que o uso de Math.signum é bom, eficaz, eficaz, mas eu gostaria de mantê-lo como um lembrete, que o método compareTo pode retornar qualquer número inteiro e multiplicar por (-1) falhará se o A implementação retorna Integer.MIN_INTEGER … E eu removi o setter porque é barato o suficiente para construir um novo PersonComparator quando necessário.

Mas mantenho o boxe porque mostra que confio em uma implementação comparável existente. Poderia ter feito algo como Comparable age1 = new Integer(person1.getAge()); mas isso parecia muito feio. A ideia era mostrar um padrão que pudesse ser facilmente adaptado a outros atributos da Pessoa, como nome, aniversário como Data e assim por diante.

Usando o Google Collections:

 class Person { private int age; public static Function GET_AGE = new Function { public Integer apply(Person p) { return p.age; } }; } public static void main(String[] args) { ArrayList 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); } } } 

Aqui está uma maneira de fazer isso.

A class java.util.Collection tem um método de sorting que recebe uma lista e um Comparador personalizado. Você pode definir seu próprio Comparador para classificar seu object Person da forma que desejar.