Ordinamento tramite comparatore – Ordine decrescente (classi definite dall’utente)

Voglio ordinare i miei oggetti in ordine decrescente usando il comparatore.

class Person { private int age; } 

Qui voglio ordinare una serie di oggetti Person.

Come posso fare questo?

È ansible eseguire l’ordinamento decrescente di una class definita dall’utente in questo modo sovrascrivendo il metodo compare () ,

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

O usando Collection.reverse() per ordinare discendente come utente Prince menzionato nel suo commento .

E puoi fare la specie crescente come questa,

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

Sostituisci il codice precedente con un’espressione Lambda (Java 8 in poi) otteniamo concisi:

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

A partire da Java 8, List ha un metodo sort () che accetta Comparator come parametro (più conciso):

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

Qui b sono dedotti come tipo Persona dall’espressione lambda.

Per quello che vale la pena qui è la mia risposta standard. L’unica cosa nuova qui è che utilizza Collections.reverseOrder (). Inoltre, mette tutti i suggerimenti in un solo esempio:

 /* ** 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] 

Ora devi implementare il Comparatore per la tua class Person. Qualcosa di simile (per ordine 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 o Integer.valueOf(a.id).compareTo(Integer.valueOf(b.id)) .

Per ridurre al minimo la confusione, è necessario implementare un comparatore crescente e convertirlo in uno discendente con un wrapper ( come questo ) new ReverseComparator(new PersonComparator()) .

Creerei un comparatore per la class persona che può essere parametrizzato con un determinato comportamento di ordinamento. Qui posso impostare l’ordinamento ma può essere modificato per consentire l’ordinamento anche per gli altri attributi.

 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); } } } 

(spero che compili ora, non ho IDE o JDK a portata di mano, codificati “ciechi”)

modificare

Grazie a Thomas, ha modificato il codice. Non direi che l’uso di Math.signum è buono, performante, efficace, ma mi piacerebbe tenerlo come promemoria, che il metodo compareTo può restituire qualsiasi intero e moltiplicando per (-1) fallirà se il l’implementazione restituisce Integer.MIN_INTEGER … E ho rimosso il setter perché è abbastanza economico da build un nuovo PersonComparator proprio quando è necessario.

Ma tengo il pugilato perché dimostra che mi baso su un’implementazione Comparable esistente. Avrebbe potuto fare qualcosa come Comparable age1 = new Integer(person1.getAge()); ma sembrava troppo brutto. L’idea era di mostrare uno schema che potesse essere facilmente adattato ad altri attributi di Person, come nome, compleanno come Data e così via.

Utilizzo delle raccolte Google:

 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); } } } 

Ecco un modo per farlo.

La class java.util.Collection ha un metodo di ordinamento che accetta un elenco e un comparatore personalizzato. Puoi definire il tuo Comparatore per ordinare il tuo object Persona come preferisci.