Özel bir sıralama düzeni tanımlamak için Karşılaştırıcıyı nasıl kullanırım?


91

Araba listesi için bir tasnif demosu geliştirmek istiyorum. Araba listesini görüntülemek için veri tablosunu kullanıyorum. Şimdi aslında listeyi araba rengine göre sıralamak istiyorum. Burada alfabetik sıraya göre sıralanmıyor. Önce Kırmızı araba, ardından Mavi vb. Gibi özel sıralama düzenimi kullanmak istiyorum.

Ben Java kullanmayı deneyin Bunun için Comparatorve Comparableancak alfabetik sadece sıralamak için izin verir.

Öyleyse, herhangi biri bana, sıralamanın daha hızlı olması için kullanılacak tekniği uygulama konusunda rehberlik edebilir mi?

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

Yanıtlar:


101

Strings kullanmak yerine arabanızın renkleri için bir numaralandırma oluşturmanızı öneririm ve numaralamanın doğal sıralaması, sabitleri bildirdiğiniz sırada olacaktır.

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

ve

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

Dize'yi PaintColor olarak değiştirirsiniz ve ardından esas olarak araba listeniz şöyle olur:

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

...

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

bu örneği nasıl çalıştırırım. ColorComparator'da PaintColors'a erişilmez. Ana yöntemin nasıl görüneceğini gösterebilirsiniz.
Deepak

çıktı nedir? her zaman GÜMÜŞ önce mi olur?
Deepak

@Deepak: evet, enumdeğerlerin doğal sırası, değerlerinin tanımlandığı sıradır.
Joachim Sauer

1
@SeanPatrickFloyd Enum'ların doğal sıralanmasına güvenmenin en iyi uygulama olduğunu düşünmüyorum.
mike

1
@mike katılmıyorum, ancak her iki bakış açısı için de geçerli argümanlar var
Sean Patrick Floyd

57

Buna ne dersin:

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

Prensip olarak, bir kullanmanın enumdaha iyi bir yaklaşım olduğunu kabul ediyorum , ancak bu sürüm farklı sıralama düzenleri tanımlamanıza izin verdiği için daha esnektir.

Güncelleme

Guava , Orderingsınıfına dahil edilen bu işlevselliğe sahiptir :

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

Bu sürüm biraz daha az ayrıntılı.


Tekrar güncelle

Java 8, Karşılaştırıcıyı daha da az ayrıntılı hale getirir:

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

Lütfen bu soruya da bakabilir misin? Teşekkürler. stackoverflow.com/questions/61934313/…
user2048204

Comparator<Car> carComparator = Comparator.comparing( c -> definedOrder.indexOf(c.getColor())); derleme hataları atıyor
Santossh Kumhar

@SantosshKumhar işte çalışan bir örnek: ideone.com/frUbym
Sean Patrick Floyd

25

Sıradaki karşılaştırıcı ...

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

Bunun şu şekilde yapılabileceğini düşünüyorum:

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

Sıralama için şunu kullanın:

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

7

Sean ve ilalex'in cevabına benzer bir şey yapmam gerekiyordu.
Ancak sıralama düzenini açıkça tanımlamak için çok fazla seçeneğim vardı ve yalnızca belirli girdileri listenin önüne, belirtilen (doğal olmayan) sırada kaydırmam gerekiyordu.
Umarım bu başka birine yardımcı olur.

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

Bunun gibi bir şey yapacağım:

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

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

Tüm krediler @ Sean Patrick Floyd'a gider :)


3

Java 8'de şöyle bir şey yapabilirsiniz:

Önce bir Enum'a ihtiyacınız var:

public enum Color {
    BLUE, YELLOW, RED
}

Araba sınıfı:

public class Car {

    Color color;

    ....

    public Color getColor() {
        return color;
    }

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

Ve sonra, araba listenizi kullanarak şunları yapabilirsiniz:

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

Bu özel bir sıralama değil.
zygimantus

Ayrıca, bunu yapmanın "işlevsel" bir yolu değil ... bunun yan etkileri var !!
TriCore

2

Bir Enum Türü tanımlayın

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

Değişim veri türü colorgelen Stringetmek Colors değiştir dönüş türü ve alıcı ve ayarlayıcı yönteminin rengin bir argüman tipineColors

Karşılaştırıcı türünü aşağıdaki gibi tanımlayın

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

Listeye öğeler ekledikten sonra, liste ve karşılaştırma nesnelerini argüman olarak ileterek Koleksiyonun sıralama yöntemini çağırın

yani, Collections.sort(carList, new ColorComparator()); ardından kullanarak yazdırın ListIterator.

tam sınıf uygulaması aşağıdaki gibidir:

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

Yalnızca basit döngüler kullanarak:

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

                }

            }
        }
    }

Ve Listedeki sıralama düzeni

public static List<String> ALARMS_LIST = Arrays.asList(
            "CRITICAL",
            "MAJOR",
            "MINOR",
            "WARNING",
            "GOOD",
            "N/A");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.