Java 类实现Comparator在探测spliterator()时生成IllegalStateException。getComparator
我有以下课程Java 类实现Comparator在探测spliterator()时生成IllegalStateException。getComparator,java,collections,spliterator,Java,Collections,Spliterator,我有以下课程 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) { ret
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);
}
}
现在Collections.reverseOrder只是Comparator的一个实现
由于这是正确的答案,我的代码期望它也能输出一个类似于上面的类名
那么,我做得不对的是什么呢?虽然拆分器的特性可能反映集合的当前内容,但它们通常仅取决于源集合的类型。因此,所有标准列表实现从不报告已排序的特征,即使它们的元素恰好当前已排序,而所有SortedSet实现始终报告已排序的特征 您可能很少需要单独使用此方法。数据处理API(如流API)可以使用幕后的特性来优化执行。例如,当流检测到数据已排序时,可能会跳过流的排序操作。但举一个不太明显的例子,当数据按元素类型的自然顺序排序时,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();
}
通常,您不会使用此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));
}
虽然拆分器的特征可能反映集合的当前内容,但它们通常仅取决于源集合的类型。因此,所有标准列表实现从不报告已排序的特征,即使它们的元素恰好当前已排序,而所有SortedSet实现始终报告已排序的特征 您可能很少需要单独使用此方法。数据处理API(如流API)可以使用幕后的特性来优化执行。例如,当流检测到数据已排序时,可能会跳过流的排序操作。但举一个不太明显的例子,当数据按元素类型的自然顺序排序时,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();
}
通常,您不会使用此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));
}
ArrayList不记得它已被排序,也不保留对比较器的引用。因此,拆分器不具有排序特性。除此之外,不要使用::compareTo作为比较器。在对可比较元素列表调用sort时,请使用Comparator.naturalOrder或仅为null。您可以调用查找。当HasCharacteristicsOrdered返回true时,可以使用getComparator。没有理由不相信这种逻辑。在你的代码中,你没有检查它,但我已经在我的第一条评论中回答过,ArrayList不记得它已经被排序了。当然,这与树集完全不同,树集甚至会以保持排序的方式插入新元素,因此它准确地知道它已排序。@Slaw yes,Stream API的引用实现仅在拆分器有空比较器时,在排序无比较器的情况下消除冗余的排序操作。这种限制没有令人信服的理由。作者说,这是因为equals并不总是告诉你两个比较器在语义上是等价的,但对我来说,这并不是不这样做的理由,因为ArrayList不记得它已被排序,也不保留对比较器的引用。因此,拆分器不具有排序特性。除此之外,不要使用::compareTo作为比较器。在对可比较元素列表调用sort时,请使用Comparator.naturalOrder或仅为null。您可以调用查找。当HasCharacteristicsOrdered返回true时,可以使用getComparator。没有理由不相信这种逻辑。在你的代码中,你没有检查它,但我已经在我的第一条评论中回答过,ArrayList不记得它已经被排序了。当然,这与树集完全不同,树集甚至会以保持排序的方式插入新元素,因此它准确地知道它已排序。@Slaw yes,Stream API的引用实现仅在拆分器有空比较器时,在排序无比较器的情况下消除冗余的排序操作。这种限制没有令人信服的理由。作者说这是因为equals并不总是告诉你两个比较器在语义上是等价的,b 但对我来说,这并不是不这样做的理由。
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));
}