Quiero desarrollar una demostración de clasificación para la lista de autos. Estoy usando la tabla de datos para mostrar la lista de autos. Ahora, en realidad, quiero ordenar la lista por color de automóvil. Aquí no está ordenado por orden alfabético. Quiero usar mi orden de clasificación personalizado, como el automóvil rojo viene primero, luego el azul, etc.
Para eso trato de usar Java Comparator
y Comparable
solo permite ordenar en orden alfabético.
Entonces, ¿alguien puede guiarme en la forma de implementar la técnica a usar para que la clasificación sea más rápida?
class Car implements Comparable<Car>
{
private String name;
private String color;
public Car(String name, String color){
this.name = name;
this.color = color;
}
//Implement the natural order for this class
public int compareTo(Car c) {
return name.compareTo(c.name);
}
static class ColorComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
String a1 = c1.color;
String a2 = c2.color;
return a1.compareTo(a2);
}
}
public static void main(String[] args) {
List<Car> carList = new ArrayList<>();
List<String> sortOrder = new ArrayList<>();
carList.add(new Car("Ford","Silver"));
carList.add(new Car("Tes","Blue"));
carList.add(new Car("Honda","Magenta"));
sortOrder.add("Silver");
sortOrder.add("Magenta");
sortOrder.add("Blue");
// Now here I am confuse how to implement my custom sort
}
}
enum
valores es el orden en que se definen sus valores.Qué tal esto:
List<String> definedOrder = // define your custom order Arrays.asList("Red", "Green", "Magenta", "Silver"); Comparator<Car> comparator = new Comparator<Car>(){ @Override public int compare(final Car o1, final Car o2){ // let your comparator look up your car's color in the custom order return Integer.valueOf( definedOrder.indexOf(o1.getColor())) .compareTo( Integer.valueOf( definedOrder.indexOf(o2.getColor()))); } };
En principio, estoy de acuerdo en que usar un
enum
es un enfoque aún mejor, pero esta versión es más flexible ya que le permite definir diferentes órdenes de clasificación.Actualizar
Guayaba tiene esta funcionalidad incorporada en su
Ordering
clase:List<String> colorOrder = ImmutableList.of("red","green","blue","yellow"); final Ordering<String> colorOrdering = Ordering.explicit(colorOrder); Comparator<Car> comp = new Comparator<Car>() { @Override public int compare(Car o1, Car o2) { return colorOrdering.compare(o1.getColor(),o2.getColor()); } };
Esta versión es un poco menos detallada.
Actualizar de nuevo
Java 8 hace que el Comparador sea aún menos detallado:
fuente
Comparador en línea ...
List<Object> objList = findObj(name); Collections.sort(objList, new Comparator<Object>() { @Override public int compare(Object a1, Object a2) { return a1.getType().compareToIgnoreCase(a2.getType()); } });
fuente
Creo que esto se puede hacer de la siguiente manera:
class ColorComparator implements Comparator<CarSort> { private List<String> sortOrder; public ColorComparator (List<String> sortOrder){ this.sortOrder = sortOrder; } public int compare(CarSort c1, CarSort c2) { String a1 = c1.getColor(); String a2 = c2.getColor(); return sortOrder.indexOf(a1) - sortOrder.indexOf(a2); } }
Para clasificar use esto:
Collections.sort(carList, new ColorComparator(sortOrder));
fuente
Tuve que hacer algo similar a la respuesta de Sean e ilalex.
Pero tenía demasiadas opciones para definir explícitamente el orden de clasificación y solo necesitaba hacer flotar ciertas entradas al frente de la lista ... en el orden especificado (no natural).
Con suerte, esto será útil para otra persona.
public class CarComparator implements Comparator<Car> { //sort these items in this order to the front of the list private static List<String> ORDER = Arrays.asList("dd", "aa", "cc", "bb"); public int compare(final Car o1, final Car o2) { int result = 0; int o1Index = ORDER.indexOf(o1.getName()); int o2Index = ORDER.indexOf(o2.getName()); //if neither are found in the order list, then do natural sort //if only one is found in the order list, float it above the other //if both are found in the order list, then do the index compare if (o1Index < 0 && o2Index < 0) result = o1.getName().compareTo(o2.getName()); else if (o1Index < 0) result = 1; else if (o2Index < 0) result = -1; else result = o1Index - o2Index; return result; } //Testing output: dd,aa,aa,cc,bb,bb,bb,a,aaa,ac,ac,ba,bd,ca,cb,cb,cd,da,db,dc,zz }
fuente
Haré algo como esto:
List<String> order = List.of("Red", "Green", "Magenta", "Silver"); Comparator.comparing(Car::getColor(), Comparator.comparingInt(c -> order.indexOf(c)))
Todos los créditos van a @Sean Patrick Floyd :)
fuente
En Java 8 puedes hacer algo como esto:
Primero necesitas un Enum:
public enum Color { BLUE, YELLOW, RED }
Clase de auto:
public class Car { Color color; .... public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } }
Y luego, usando su lista de autos, simplemente puede hacer:
fuente
Defina un tipo de enumeración como
public enum Colors { BLUE, SILVER, MAGENTA, RED }
Cambiar el tipo de datos de
color
desdeString
aColors
Cambiar el tipo de retorno y el tipo de argumento del getter y el método de setter de colorColors
Defina el tipo de comparador de la siguiente manera
static class ColorComparator implements Comparator<CarSort> { public int compare(CarSort c1, CarSort c2) { return c1.getColor().compareTo(c2.getColor()); } }
después de agregar elementos a la Lista, llame al método de clasificación de Colección pasando la lista y los objetos comparadores como argumentos
es decir,
Collections.sort(carList, new ColorComparator());
luego imprima usandoListIterator
.La implementación de clase completa es la siguiente:
package test; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.ListIterator; public class CarSort implements Comparable<CarSort>{ String name; Colors color; public CarSort(String name, Colors color){ this.name = name; this.color = color; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Colors getColor() { return color; } public void setColor(Colors color) { this.color = color; } //Implement the natural order for this class public int compareTo(CarSort c) { return getName().compareTo(c.getName()); } static class ColorComparator implements Comparator<CarSort> { public int compare(CarSort c1, CarSort c2) { return c1.getColor().compareTo(c2.getColor()); } } public enum Colors { BLUE, SILVER, MAGENTA, RED } public static void main(String[] args) { List<CarSort> carList = new ArrayList<CarSort>(); List<String> sortOrder = new ArrayList<String>(); carList.add(new CarSort("Ford Figo",Colors.SILVER)); carList.add(new CarSort("Santro",Colors.BLUE)); carList.add(new CarSort("Honda Jazz",Colors.MAGENTA)); carList.add(new CarSort("Indigo V2",Colors.RED)); Collections.sort(carList, new ColorComparator()); ListIterator<CarSort> itr=carList.listIterator(); while (itr.hasNext()) { CarSort carSort = (CarSort) itr.next(); System.out.println("Car colors: "+carSort.getColor()); } } }
fuente
Usando bucles simples:
public static void compareSortOrder (List<String> sortOrder, List<String> listToCompare){ int currentSortingLevel = 0; for (int i=0; i<listToCompare.size(); i++){ System.out.println("Item from list: " + listToCompare.get(i)); System.out.println("Sorting level: " + sortOrder.get(currentSortingLevel)); if (listToCompare.get(i).equals(sortOrder.get(currentSortingLevel))){ } else { try{ while (!listToCompare.get(i).equals(sortOrder.get(currentSortingLevel))) currentSortingLevel++; System.out.println("Changing sorting level to next value: " + sortOrder.get(currentSortingLevel)); } catch (ArrayIndexOutOfBoundsException e){ } } } }
Y orden de clasificación en la lista
public static List<String> ALARMS_LIST = Arrays.asList( "CRITICAL", "MAJOR", "MINOR", "WARNING", "GOOD", "N/A");
fuente