collection.sort для определения порядка сортировки по двум элементам? - PullRequest
2 голосов
/ 01 февраля 2012

Я пишу свой собственный класс компаратора, который называется PercentComparator и называется следующим образом:

Collections.sort(engineList, new PercentageComparator());

, где engineList - Список объектов, где каждый объект имеет значения в процентах завершения, и вышеупомянутые функции сортировки работают нормально.

Теперь клиент просит добавить еще один заказ по элементам по типу продукта наряду с процентами. Можем ли мы сделать порядок сортировки по двум элементам объектов?

Ответы [ 9 ]

4 голосов
/ 01 февраля 2012
Collections.sort(engineList, new PercentageComparator());
Collections.sort(engineList, new ProductTypeComparator());

Сортировка по типу продукта и для одинаковых типов продуктов сортировка по процентам.Это работает, потому что

Этот сорт гарантированно будет стабильным : равные элементы не будут переупорядочены в результате сортировки.

http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort%28java.util.List%29

3 голосов
/ 01 февраля 2012

Создайте свой собственный новый Comparator, который вызывает PercentageComparator после сравнения типа продукта.

1 голос
/ 01 февраля 2012

Если я правильно понял:

class EngineComparator implements Comparator<Engine> {
    @Override
    public int compare(Engine o1, Engine o2) {
        int result = o1.getProdType().compareTo(o2.getProdType());
        return (result == 0) ? o1.getPercent().compareTo(o2.getPercent()) : result;
    }
}

Вот как сортируется коллекция:


Prod-Type   Percent
=======================
  A         1
  A         2
  A         3
  B         1
  B         2
  B         3
  C         1
  C         2
  C         3
0 голосов
/ 01 февраля 2012

Для более общего решения взгляните на Apache Common ComparatorChain , из Javadocs:

ComparatorChain - это компаратор, который объединяет один или несколько компараторов в последовательности. ComparatorChain вызывает каждый Comparator в последовательности, пока либо 1) ни один из Comparator не вернет ненулевой результат (и этот результат затем будет возвращен), или 2) ComparatorChain исчерпан (и ноль будет возвращен). Этот тип сортировки очень похож на многостолбцовую сортировку в SQL, и этот класс позволяет классам Java эмулировать такое поведение при сортировке списка.

0 голосов
/ 01 февраля 2012

Сначала создайте другую реализацию компаратора, которая сравнивает только по типу продукта. Тогда назовите это:

Collections.sort(engineList, new CompoundComparator(productTypeCmp, percentageCmp));

Вот реализация составного компаратора, он делегирует сравнение переданным компараторам в том порядке, в котором они были переданы.

class CompoundComparator implements Comparator<Engine>{ 
    private List<Comparator> comparators;
    public CompoundComparator(Comparator<Engine> ... comparators){
       this.comparators = Arrays.asList(comparators);
    }
    public int compare(Engine o1, Engine o2){
       int cmp = 0;
       Iterator cmpIter = comparators.iterator();
       while(cmp == 0 && cmpIter.hasNext()){
          cmp = cmpIter.next().compare(o1, o2);
       }
       return cmp;
    }

}

Предполагая, что объекты имеют тип Engine.

0 голосов
/ 01 февраля 2012

Обычно ваш Comparator будет тестировать по одному полю за раз, пока не появится разница.Например, если процент был наивысшим приоритетом, за которым следовал тип продукта, а у вашего класса было умное имя StackOverflow1:

    Comparator<StackOverflow1> COMPARATOR = new Comparator<StackOverflow1>() {

          @Override
          public int compare(StackOverflow1 o1, StackOverflow1 o2) {
             int result = Double.compare(o1.percent, o2.percent);
             if (result == 0)
                result = o1.productType - o2.productType;
                // NOTE - above line isn't really safe but used for illustration...

             // any more tests of fields here...

             return result;
          }         
   };

Если вам нужна тонна гибкости, непременно напишите несколько отдельных компараторов исоедините их в цепочку (как предлагали другие), но во многих случаях это излишне - вам нужен только один.

0 голосов
/ 01 февраля 2012

Вы можете создать составной компаратор, который имеет два компаратора и возвращает значение от второго компаратора, если первый компаратор возвращает 0.

Вы можете даже расширить этот процесс, используя список из N компараторов, и вернутьпервый ненулевой результат или возвращает 0, если достигнут конец списка.

0 голосов
/ 01 февраля 2012

Ваш метод сортировки может выполнять любые виды упорядочения по вашему желанию, при условии что вся соответствующая (сопоставимая) информация содержится в объектах, передаваемых методу. Другими словами, ваши сортируемые объекты должны содержать все сортируемые подполя. И вам придется написать другой метод / класс сортировки, чтобы справиться с ним.

0 голосов
/ 01 февраля 2012

Если это будет отдельная сортировка, сделайте отдельный компаратор и используйте их в «цепочке». Или сделайте свой EngineComparator(Boolean sortPercentDesc, Boolean sortProductDesc), который, на мой взгляд, мог бы быть лучше, так как его было бы легче поддерживать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...