Сопоставимый класс с полем List <String> - PullRequest
0 голосов
/ 16 мая 2018

У меня есть простой класс, который хранит целое число и список строк.

Поскольку я хочу использовать этот класс в TreeSet<>, он должен быть Comparable.Но при попытке использовать класс Java 8 Comparator я не могу сравнить свой внутренний список.У меня следующая ошибка:

Неверный тип возврата в справочнике методов: невозможно преобразовать java.util.List в U

Я думаю, что есть очень простой способ сделатьэто, но я не мог это выяснить.

Как это сделать?

public class MyClass implements Comparable<MyClass> {

    private final int          someInt;
    private final List<String> someStrings;

    public MyClass (List<String> someStrings, int someInt) {
        this.someInt = someInt;
        this.someStrings = new ArrayList<>(someStrings);
    }

    @Override
    public int compareTo(MyClass other) {
        return
                Comparator.comparing(MyClass::getSomeInt)
                        .thenComparing(MyClass::getSomeStrings) // Error here
                        .compare(this, other);
    }

    public int getSomeInt() {
        return someInt;
    }

    public List<String> getSomeStrings() {
        return someStrings;
    }
}

Редактировать 1

Я просто хочу, чтобы список строк сравнивался самым простым способом(неявно используя String.compareTo()).

Обратите внимание, что теперь я хочу отсортировать List<String>, но я хочу, чтобы оно было Comparable, чтобы MyClass также было сопоставимо, и, наконец, я могу вставить MyClass экземпляров в TreeSet<MyClass>.

A также видели в JavaDoc следующее:

java.util.Comparator<T> public Comparator<T>
    thenComparing(@NotNull Comparator<? super T> other)

Например, для сортировки коллекции String на основе длины изатем без учета регистра естественное упорядочение, компаратор может быть составлен с использованием следующего кода:

Comparator<String> cmp = Comparator.comparingInt(String::length)
   .thenComparing(String.CASE_INSENSITIVE_ORDER);

Кажется, это подсказка, но я не знаю, как применить его к этому простому примеру.

Изменить 2

Допустим, я хочу, чтобы мои List<String> были отсортированы следующим образом:

  • Fiпервая проверка: List.size() (короче меньше, чем большая);
  • Вторая проверка на совпадение размеров: сравнение одного за другим каждого элемента обоих списков до нахождения того, где метод String.compareTo возвращает 1 или-1.

Как сделать это с лямбдами в методе my compareTo?

Редактировать 3

Это не дублирует этот вопрос , потому что я хочу знать, как построить компаратор класса, который содержит List<String> с вызовами Java 8 Comparable вызовов.

1 Ответ

0 голосов
/ 16 мая 2018

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

(то есть [a, b, c] < [b, a, c])

Создайте пользовательский компаратор для списка, возвращающего объединение вашей строки списка:

Comparator<List<String>> listComparator = (l1, l2) -> {
     if (l1.size() != l2.size()) {
        return l1.size() - l2.size();
     }
     for (int i = 0; i < l1.size(); i++) {
        int strCmp = l1.get(i).compareTo(l2.get(i));
        if (strCmp != 0) {
            return strCmp;
        }
     }
     return 0; // Two list equals
};

Затем вы можете сравнить, используя этот пользовательский компаратор:

@Override
public int compareTo(MyClass other) {
    return  Comparator.comparing(MyClass::getSomeInt)
                    .thenComparing(Comparator.comparing(MyClass:: getSomeStrings , listComparator))
                    .compare(this, other);
}

Если вы хотите [a, b, c] = [b, a, c], тогда у вас естьотсортировать список перед сравнением:

public String getSomeStringsJoined() {
    return getSomeStrings().stream().sort(Comparator.naturalOrder()).collect(Collectors.joining());
}
...