Сортировка arraylist строковых массивов Java

У меня есть программа, которая берет слово и словарь текстового файла и ищет в словаре комбинации слов, которые равны (анаграммы) заданному слову.

В итоге я получаю Arraylist массивов String, каждый массив представляет собой решение, содержащее используемые им слова, а Arraylist — это все решения.

Затем я перебираю массив и сортирую массивы как:

List<String> list = Arrays.asList(array);
list.sort(Comparator.comparing(String::length).reversed().thenComparing(String::compareTo));

который сначала сортируется по длине слова (по убыванию), а затем использует алфавитный порядок для разрешения конфликтов для слов одинаковой длины.

Теперь у меня отсортированы отдельные массивы, но я пытаюсь отсортировать их в массиве по определенным правилам:

  • по возрастанию количества слов
  • для массивов, содержащих одинаковое количество слов, и все слова имеют одинаковую длину, массивы сортируются в алфавитном порядке.
  • одинаковое количество слов, но разной длины: сначала самая длинная неравная длина. Например, если длина a[0] == длина b[0], но длина b[1]>длина a[1], то b идет первым.

Они уже хранятся по возрастанию количества слов, так как сначала находятся однословные решения, затем 2 слова и так далее, которые добавляются к массиву.

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


person user7433346    schedule 23.01.2017    source источник


Ответы (1)


Во-первых, нет необходимости преобразовывать массив в List для сортировки.

Во-вторых, вы должны использовать thenComparing(Comparator.naturalOrder()) вместо thenComparing(String::compareTo), так как при этом будет использоваться одиночка Comparator, а не создание нового Comparator, делегирующего ссылку на метод.

Что касается вашего вопроса, я не думаю, что для этого существует Comparator, поэтому просто создайте свой собственный. Строительство комплекса Comparator с использованием thenComparing() — это хорошо, но не всегда правильно.

Таким образом, ваш код может быть следующим: (при условии, что я правильно понял ваши критерии сортировки):

List<String[]> solutions = /* code here */;

// First, sort each individual solution (array)
for (String[] solution : solutions) {
    Arrays.sort(solution, Comparator.comparing(String::length)
                                    .reversed()
                                    .thenComparing(Comparator.naturalOrder()));
}

// Second, sort the solutions (list)
solutions.sort((solution1, solution2) -> {
        // 1) By number of words (ascending)
        int cmp = Integer.compare(solution1.length, solution2.length);
        // 2) By length of word (descending)
        for (int i = 0; cmp == 0 && i < solution1.length; i++)
            cmp = Integer.compare(solution2[i].length(), solution1[i].length());
        // 3) Alphabetically (ascending)
        for (int i = 0; cmp == 0 && i < solution1.length; i++)
            cmp = solution1[i].compareTo(solution2[i]);
        return cmp;
});
person Andreas    schedule 23.01.2017