2009-12-22 23 views

Respuesta

14
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] 

Ahora tiene que implementar el Comparador para su clase Persona. Algo así como (para orden ascendente): 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)).

Para minimizar la confusión, debe implementar un Comparador ascendente y convertirlo en uno descendente con un contenedor (like this) new ReverseComparator<Person>(new PersonComparator()).

+0

Ahora que es un ejemplo un poco confuso, porque String implementa Comparable. Y eso -1 no es lo más directo. – Bozho

+1

El mejor argumento contra -1 * x es que '-1 * Integer.MIN_VALUE == Integer.MIN_VALUE'. Que no es lo que quieres Cambié los argumentos que es más fácil de todos modos. –

+1

Y supongo que es un ReverseComparator, en lugar de Reserve ... –

0

La clase s java.util.Collection tiene un método de ordenación que tiene una lista y una personalizada Comparator. Puede definir su propio Comparador para ordenar su objeto Persona como desee.

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

} 

Aquí hay una manera de hacerlo.

13

Crearía un comparador para la clase de persona que se puede parametrizar con un cierto comportamiento de clasificación. Aquí puedo establecer el orden de clasificación, pero puede modificarse para permitir la clasificación de los atributos de otras personas también.

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

(espero que compila ahora, no tengo IDE o JDK a la mano, codificados 'a ciegas')

Editar

Gracias a Thomas, editar el código. No diría que el uso de Math.signum es bueno, efectivo, pero me gustaría recordarlo, el método compareTo puede devolver cualquier entero y multiplicar por (-1) no funcionará si el la implementación devuelve Integer.MIN_INTEGER ... Y eliminé el setter porque es lo suficientemente barato como para construir un nuevo PersonComparator justo cuando es necesario.

Pero mantengo el boxeo porque muestra que confío en una implementación Comparable existente. Pudo haber hecho algo como Comparable<Integer> age1 = new Integer(person1.getAge()); pero parecía demasiado feo. La idea era mostrar un patrón que se pudiera adaptar fácilmente a los atributos de otra Persona, como el nombre, el cumpleaños como Fecha y así sucesivamente.

+4

Había una vez un buen hábito de dejar un comentario para ayudar al autor humillado a mejorar su mensaje. –

+0

No he votado negativamente, pero 'compare * (-1)' es propenso al desbordamiento. Cometí el mismo error en mi publicación inicial. –

+0

Y SortOrder se debe establecer en el constructor y ser final. Usar un contenedor es un mejor enfoque, supongo: 'new Reverse (nuevo PersonComparator())' –

4

Usar colecciones de Google:

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()); 
} 
+2

Overshooting con estilo :) – Esko

58

Para cuál es su valor aquí está mi respuesta estándar. Lo único nuevo aquí es que usa Collections.reverseOrder(). Además de que pone todas las sugerencias en un ejemplo:

/* 
** 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); 
    } 
} 
+0

esto realmente funcionó para mí, y también es una solución muy fácil (solo una línea). –

+0

¡Ejemplo perfecto! Gracias. –

+0

¿Hay alguna manera de ordenar Cadenas en un TreeSet usando un comparador como este? Lo mismo, personas por edad. – Zeff520

82

Se puede hacer descender el tipo de una clase definida por el usuario de esta manera reemplazando el método compare(),

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

O utilizando Collection.reverse() para ordenar descendiendo como usuario Prince mencionado en his comment.

Y lo puede hacer la clasificación ascendente como este,

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

reemplazar el código anterior con una expresión Lambda (Java 8 en adelante) obtenemos concisa:

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

A partir de Java 8, Lista tiene sort() método que toma Comparator como parámetro (más concisa):

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

Aquí a y b se deducen como tipo de persona por expresión lambda.

+18

O simplemente puede usar 'Collections.reverseOrder (...)' para la ordenación descendente. – Prince

+1

@Prince No me gusta este enfoque, me obliga a mirar el método original para ver cómo se ordenan las cosas para empezar (sin invertir). –

+1

Vale la pena mencionar que 'compareToIgnoreCase' también es útil cuando se comparan objetos' String' , la mayoría de las veces lo uso en lugar de simplemente 'compareTo' –

Cuestiones relacionadas