[java] Comparator를 사용하여 사용자 지정 정렬 순서를 정의하려면 어떻게합니까?

자동차 목록에 대한 분류 데모를 개발하고 싶습니다. 자동차 목록을 표시하기 위해 데이터 테이블을 사용하고 있습니다. 이제 실제로 자동차 색상별로 목록을 정렬하고 싶습니다. 여기서는 알파벳 순서로 정렬하지 않습니다. Red car가 먼저 온 다음 Blue 등의 맞춤 정렬 순서를 사용하고 싶습니다.

내가 자바를 사용하려고 것을 들어 Comparator하고 Comparable있지만 알파벳 순서로만 정렬 할 수 있습니다.

따라서 어느 누구도 정렬이 더 빨라지도록 사용할 기술을 구현하는 방법을 안내 할 수 있습니까?

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



답변

문자열을 사용하는 대신 자동차 색상에 대한 열거 형을 만드는 것이 좋으며 열거 형의 자연스러운 순서는 상수를 선언하는 순서가됩니다.

public enum PaintColors {
    SILVER, BLUE, MAGENTA, RED
}

 static class ColorComparator implements Comparator<CarSort>
 {
     public int compare(CarSort c1, CarSort c2)
     {
         return c1.getColor().compareTo(c2.getColor());
     }
 }

String을 PaintColor로 변경하면 기본적으로 자동차 목록이 다음과 같이 변경됩니다.

carList.add(new CarSort("Ford Figo",PaintColor.SILVER));

...

Collections.sort(carList, new ColorComparator());


답변

이건 어때:

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

원칙적으로를 사용하는 enum것이 훨씬 더 나은 접근 방식 이라는 데 동의 하지만이 버전은 다른 정렬 순서를 정의 할 수 있기 때문에 더 유연합니다.

최신 정보

Guava 에는 다음과 같은 기능이 Ordering클래스에 포함되어 있습니다.

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

이 버전은 좀 덜 장황합니다.


다시 업데이트

Java 8은 Comparator를 훨씬 덜 장황하게 만듭니다.

Comparator<Car> carComparator = Comparator.comparing(
        c -> definedOrder.indexOf(c.getColor()));


답변

라인 비교기 …

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


답변

다음과 같이 할 수 있다고 생각합니다.

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

정렬하려면 다음을 사용하십시오.

Collections.sort(carList, new ColorComparator(sortOrder));


답변

나는 Sean과 ilalex의 대답과 비슷한 것을해야했습니다.
하지만 정렬 순서를 명시 적으로 정의 할 수있는 옵션이 너무 많았고 특정 항목을 지정된 (비 자연스러운) 순서로 목록의 맨 앞으로 띄우기 만하면되었습니다.
다른 사람에게 도움이되기를 바랍니다.

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
}


답변

나는 다음과 같이 할 것입니다.

List<String> order = List.of("Red", "Green", "Magenta", "Silver");

Comparator.comparing(Car::getColor(), Comparator.comparingInt(c -> order.indexOf(c)))

모든 크레딧은 @Sean Patrick Floyd로 이동합니다. 🙂


답변

Java 8에서는 다음과 같이 할 수 있습니다.

먼저 Enum이 필요합니다.

public enum Color {
    BLUE, YELLOW, RED
}

자동차 등급 :

public class Car {

    Color color;

    ....

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }
}

그런 다음 자동차 목록을 사용하여 다음을 수행 할 수 있습니다.

Collections.sort(carList, Comparator:comparing(CarSort::getColor));