Làm cách nào để sử dụng Bộ so sánh để xác định thứ tự sắp xếp tùy chỉnh?


91

Tôi muốn phát triển một bản demo sắp xếp cho danh sách xe hơi. Tôi đang sử dụng bảng dữ liệu để hiển thị danh sách xe. Bây giờ thực sự tôi muốn sắp xếp danh sách theo màu xe. Ở đây nó không được sắp xếp theo thứ tự bảng chữ cái. Tôi muốn sử dụng thứ tự sắp xếp tùy chỉnh của mình như xe Đỏ đến trước, sau đó đến Xanh lam, v.v.

Đối với điều đó, tôi cố gắng sử dụng Java ComparatorComparablenó chỉ cho phép sắp xếp theo thứ tự bảng chữ cái.

Vậy có bác nào có thể hướng dẫn em cách thực hiện kỹ thuật sử dụng để việc phân loại trở nên nhanh chóng hơn không ạ.

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

Câu trả lời:


101

Tôi khuyên bạn nên tạo một enum cho màu xe của bạn thay vì sử dụng Chuỗi và thứ tự tự nhiên của enum sẽ là thứ tự mà bạn khai báo các hằng số.

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

Bạn thay đổi Chuỗi thành Màu sơn và sau đó trong chính danh sách ô tô của bạn trở thành:

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

...

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

Làm thế nào để tôi chạy ví dụ này. Màu sắc không được truy cập trong ColorComparator. Bạn có thể minh họa phương thức chính trông như thế nào không.
Deepak

đầu ra là gì? nó luôn luôn BẠC đầu tiên?
Deepak

@Deepak: vâng, thứ tự tự nhiên của các enumgiá trị là thứ tự mà các giá trị của nó được xác định.
Joachim Sauer

1
@SeanPatrickFloyd Tôi không nghĩ rằng dựa vào thứ tự tự nhiên của enum là cách tốt nhất.
mike

1
@ Mike Tôi không đồng ý, nhưng có những lý lẽ hợp lệ cho cả hai quan điểm
Sean Patrick Floyd

57

Còn cái này thì sao:

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

Về nguyên tắc, tôi đồng ý rằng sử dụng một enumcách tiếp cận thậm chí còn tốt hơn, nhưng phiên bản này linh hoạt hơn vì nó cho phép bạn xác định các thứ tự sắp xếp khác nhau.

Cập nhật

Ổi có chức năng này được xếp vào loại của nó 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());
    }
}; 

Phiên bản này ít dài dòng hơn một chút.


Cập nhật lại

Java 8 làm cho Bộ so sánh ít dài dòng hơn:

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

Bạn cũng có thể vui lòng xem xét câu hỏi này. Cảm ơn bạn. stackoverflow.com/questions/61934313/…
user2048204

25

Bộ so sánh trong dòng ...

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

Tôi nghĩ điều này có thể được thực hiện như sau:

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

Để phân loại, hãy sử dụng cái này:

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

7

Tôi đã phải làm điều gì đó tương tự như câu trả lời của Sean và ilalex.
Nhưng tôi có quá nhiều lựa chọn để xác định rõ ràng thứ tự sắp xếp và chỉ cần đưa một số mục nhập nhất định lên đầu danh sách ... theo thứ tự đã chỉ định (không tự nhiên).
Hy vọng rằng điều này là hữu ích cho người khác.

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

Tôi sẽ làm một cái gì đó như thế này:

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

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

Tất cả các khoản tín dụng được chuyển đến @Sean Patrick Floyd :)


3

Trong Java 8, bạn có thể làm như sau:

Trước tiên bạn cần một Enum:

public enum Color {
    BLUE, YELLOW, RED
}

Hạng ô tô:

public class Car {

    Color color;

    ....

    public Color getColor() {
        return color;
    }

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

Và sau đó, sử dụng danh sách xe của bạn, bạn có thể chỉ cần làm:

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

Đây không phải là một loại tùy chỉnh.
zygimantus

Ngoài ra, nó không phải là một cách "chức năng" để làm điều đó ... điều này có ảnh hưởng phụ !!
TriCore

2

Xác định một Loại Enum là

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

Thay đổi kiểu dữ liệu colortừ Stringthành Colors Thay đổi kiểu trả về và kiểu đối số của màu phương thức getter và setter thànhColors

Xác định loại bộ so sánh như sau

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

sau khi thêm các phần tử vào Danh sách, hãy gọi phương thức sắp xếp của Bộ sưu tập bằng cách chuyển các đối tượng danh sách và bộ so sánh làm đối số

tức là, Collections.sort(carList, new ColorComparator()); sau đó in bằng cách sử dụng ListIterator.

triển khai toàn bộ lớp như sau:

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

Chỉ sử dụng các vòng lặp đơn giản:

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

                }

            }
        }
    }

Và sắp xếp thứ tự trong Danh sách

public static List<String> ALARMS_LIST = Arrays.asList(
            "CRITICAL",
            "MAJOR",
            "MINOR",
            "WARNING",
            "GOOD",
            "N/A");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.