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


91

자동차 목록에 대한 분류 데모를 개발하고 싶습니다. 자동차 목록을 표시하기 위해 데이터 테이블을 사용하고 있습니다. 이제 실제로 자동차 색상별로 목록을 정렬하고 싶습니다. 여기서는 알파벳 순서로 정렬하지 않습니다. 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             
    }
}

답변:


101

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

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

이 예제를 어떻게 실행합니까 .PaintColors는 ColorComparator에서 액세스되지 않습니다. 주 메서드가 어떻게 생겼는지 설명 할 수 있습니다.
Deepak 2011 년

출력은 무엇입니까? 항상 실버 먼저입니까?
Deepak 2011 년

@Deepak : 예, enum값 의 자연스러운 순서 는 값이 정의 된 순서입니다.
Joachim Sauer 2011 년

1
@SeanPatrickFloyd enum의 자연스러운 순서에 의존하는 것이 모범 사례라고 생각하지 않습니다.
마이크

1
@ 마이크 나는 동의하지만,보기의 두 점에 대한 유효한 인수가 있습니다
숀 패트릭 플로이드

57

이건 어때:

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

이 질문도 살펴볼 수 있습니까? 감사합니다. stackoverflow.com/questions/61934313/…
user2048204

25

라인 비교기 ...

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

11

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

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

7

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

4

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

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

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

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


3

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

이것은 사용자 정의 정렬이 아닙니다.
zygimantus

게다가, 그것은 그것을하는 "기능적인"방법이 아닙니다… 이것은 부작용이 있습니다 !!
TriCore

2

하나의 열거 형 유형을 다음과 같이 정의합니다.

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

의 데이터 유형을 color에서 String로 변경Colors 변경 getter 및 setter 메서드의 반환 유형 및 인수 유형 변경Colors

다음과 같이 비교기 유형을 정의하십시오.

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

List에 요소를 추가 한 후 list와 comparator 객체를 인자로 전달하여 Collection의 sort 메서드를 호출합니다.

즉, Collections.sort(carList, new ColorComparator()); 다음 사용하여 인쇄 ListIterator.

전체 클래스 구현은 다음과 같습니다.

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

0

간단한 루프 사용 :

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){

                }

            }
        }
    }

그리고 목록에서 정렬 순서

public static List<String> ALARMS_LIST = Arrays.asList(
            "CRITICAL",
            "MAJOR",
            "MINOR",
            "WARNING",
            "GOOD",
            "N/A");
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.