Класс, реализующий Comparator, создает IllegalStateException при проверке spliterator (). GetComparator - PullRequest
1 голос
/ 06 апреля 2020

У меня следующий класс

class A implements Comparable<A> {

    private String name;

    public A(String name) {
        this.name = name;
    }

    public String getName() {
       return name;
    }

    @Override
    public int compareTo(A o) {
        return o.getName().compareTo(this.name);
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        A a = (A) o;
        return name.equals(a.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

Теперь я понимаю, что следующий код должен выдавать какое-то имя класса или ноль, но не IllegalStateException, как указано в документе java, в котором написано

Если источник этого Spliterator отсортирован Компаратором, возвращает этот Компаратор. Если источник отсортирован в естественном порядке, возвращает ноль. В противном случае, если источник не отсортирован, генерируется исключение IllegalStateException.

List<A> arrayList = new ArrayList<>();
arrayList.add(new A("Y"));
arrayList.add(new A("G"));
arrayList.add(new A("J"));
arrayList.add(new A("A"));
arrayList.add(new A("Z"));

arrayList.sort(A::compareTo);
Comparator<? super A> comparator = arrayList.spliterator().getComparator();
System.out.println(comparator);

РЕДАКТИРОВАТЬ 2

Я считаю, что не могу заставить вас понять, что я ищу. Возьмите это как пример:

SortedSet<String> set = new TreeSet<>( Collections.reverseOrder() );
set.add("A");
set.add("D");
set.add("C");
set.add("B");
System.out.println(set);
System.out.println(set.spliterator().getComparator());

Это выводит как

[D, C, B, A]
java.util.Collections$ReverseComparator@7852e922

Теперь Collections.reverseOrder () является просто реализацией Comparator

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

Так что же я не так делаю?

1 Ответ

3 голосов
/ 06 апреля 2020

Хотя характеристики Spliterator могут отражать текущее содержимое коллекции, они обычно зависят от типа только исходной коллекции. Таким образом, все стандартные реализации List никогда не сообщают о SORTED характеристиках c, даже когда их элементы в настоящее время сортируются, тогда как все реализации SortedSet всегда сообщают о SORTED характеристиках c.

* 1009. * Вам редко может понадобиться использовать этот метод самостоятельно. API обработки данных, такие как Stream API, могут использовать характеристики за сценой для оптимизации выполнения. Например, операция sorted для Stream может быть пропущена при обнаружении того, что данные уже отсортированы. Но если назвать менее очевидный пример, distinct может работать по-разному, когда данные сортируются по естественному порядку типа элемента.

Кроме того, состояние конвейера потока может служить примером случая, когда характеристики не определяются типом:

public static void main(String[] args) {
    check(Stream.of("foo", "bar").filter(x -> true));
    check(Stream.of("foo", "bar").sorted().filter(x -> true));
}
private static void check(Stream<?> s) {
    System.out.println("Type: "+s.getClass());
    System.out.println("sorted: "+s.spliterator().hasCharacteristics(Spliterator.SORTED));
    System.out.println();
}
Type: class java.util.stream.ReferencePipeline$2
sorted: false

Type: class java.util.stream.ReferencePipeline$2
sorted: true

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

TreeMap<String, Integer> map = new TreeMap<>(Comparator.comparingInt(String::length));

Spliterator<Map.Entry<String, Integer>> sp = map.entrySet().spliterator();
if(sp.hasCharacteristics(Spliterator.SORTED)) {
    Comparator<? super Map.Entry<String, Integer>> comparator = sp.getComparator();
    System.out.println("Entry comparator: " + comparator);
    Map.Entry<String, Integer> e1 = new AbstractMap.SimpleEntry<>("some", 5);
    Map.Entry<String, Integer> e2 = new AbstractMap.SimpleEntry<>("string", 3);
    System.out.println(BinaryOperator.maxBy(comparator).apply(e1, e2));
}
...