2015-11-10 3 views
0

У меня есть запятые строки которая содержит критерии сортировки для сортировки списка студентов:Сортировка логики настроена струнный порядка

Input: 
String sortOrder = "height, weight, age" 
List<student> students; 

Каждые из элементов выше, компараторы на объекте студентов, которые сортируют объект Student с некоторой сложной логикой. Мне нужно знать, как лучше всего перевести порядок сортировки, как он появляется в строке sortOrder, и активировать соответствующие компараторы в этом порядке. Таким образом, в приведенном выше примере сравнительный компаратор высоты будет работать первым, а последний - последним.

+2

«Таким образом, для приведенного выше примера, высота компаратора будет работать первый и возраст Последний.". Сортировка не работает. Вы сортируете по высоте. Когда высоты равны, вы сортируете по весу. Когда весы равны, вы сортируете по возрасту. –

+0

Просьба пояснить: вам нужен один вид с тремя (или любыми цифрами) уровнями, как описано в @GilbertLeBlanc? Или три разных типа, выполненных в порядке, указанном в 'String'? –

+0

@ ErickG.Hagstrom Я искал последний. –

ответ

2

Вы можете сделать HashMap, сопоставляя эти слова с Comparator объектов. Затем с помощью компараторов для сортировки

Map<String, Comparator<student>> comparators = new HashMap<>(); 

после добавления Comparator объектов comparators так:

comparators.put("height", Comparator.comparingDouble(student::getHeight)); 

Если вы хотите, чтобы выполнять различные виды последовательно, просто пройти через слова в sortOrder и применить например

for (String comp : sortOrder.split(", ")) 
    Collections.sort(students, comparators.get(comp)); 
+0

Это не сработает. В итоге вы получите список, отсортированный по последнему полю во входной строке. Вы должны комбинировать все компараторы с помощью 'thenComparing':' Comparator comp = Pattern.compile (",") .splitAsStream (sortOrder) .map (comparators :: get) .reduce (Comparator :: thenComparing) .get(); ' – Misha

+0

Правильно и неправильно, @ Миша. Этот ответ не будет работать, исправьте. Но это более чем простая проблема сортировки, несмотря на название. См. Комментарии по этому вопросу и другие вопросы, заданные ОП сегодня. Это сбивает с толку. –

+0

@ Миша ОП упомянул в комментариях, что это именно то, что он хочет, 3 разных рода 1 за другим. Он может захотеть сделать что-то со списком, прежде чем он будет повторно отсортирован, например. распечатайте его. В сущности, я писал «Компаратор» с более разумным поведением, пока не увидел комментарии OP, а затем написал это. –

1

Если я правильно понимаю, что вы хотите, вы хотите отсортировать список студентов по их высотам, затем их вес, а затем их возраст. Но вы хотите, чтобы этот список свойств был динамическим.

Это означает, что нам необходимо реализовать пользовательский Comparator, который работает с данным свойством данного класса.

Первой реализацией может быть создание Map, где каждое свойство String сопоставляется с ассоциированным Comparator. Это был бы чистый подход (см. Комментарий @Manos Nikolaidis и комментарий Миши для этой реализации).

Истинное динамическое решение возможно с использованием немного отражения: сначала извлекается объявленное поле, имеющее заданное имя данного класса. Он доступен, поскольку это поле, скорее всего, личное. Наконец, возвращается значение Comparator, сравнивающее значение этого поля для каждого ученика. Этот код предполагает слепо, что целевое свойство действительно Comparable (в противном случае, почему мы хотели бы сравнить это поле?).

private static <U> Comparator<U> comparingProperty(String property, Class<U> clazz) { 
    try { 
     Field field = clazz.getDeclaredField(property); 
     field.setAccessible(true); 
     return Comparator.comparing(s -> { 
      try { 
       @SuppressWarnings("unchecked") 
       Comparable<Object> comparable = (Comparable<Object>) field.get(s); 
       return comparable; 
      } catch (IllegalAccessException e) { 
       throw new AssertionError(e); 
      } 
     }); 
    } catch (NoSuchFieldException e) { 
     throw new AssertionError(e); 
    } 
} 

После этого у нас есть этот компаратор полезности, мы можем легко отсортировать список студентов. Поток свойств сортировки создается путем разбиения на "," и обрезки результатов. Затем каждое свойство отображается на его соответствующий Comparator и, наконец, этот поток уменьшается путем объединения всех компараторов вместе с Comparator::thenComparing:

students.sort(Stream.of(sortOrder.split(",")) 
        .map(String::trim) 
        .map(s -> comparingProperty(s, Student.class)) 
        .reduce(Comparator::thenComparing) 
        .get() 
      ); 
Смежные вопросы