在 Comparator 中使用 String 时出错
Having an error when using String in Comparator
我正在尝试创建一个 class 可比较的实现。当所有 class 元素都是整数时,一切正常。当我使用 String 并使用 comparing
而不是 comparingInt
时,我收到以下错误。
Comparator 类型的泛型方法 comparing(Function) 的类型参数数量不正确;它不能用参数
参数化
类型myClass没有定义这里适用的getFrom(T)
public class myClass implements Comparable<myClass> {
@Column (name="From")
private String from;
@Column (name="To")
private String to;
@Column (name="With")
private String with;
@Column (name="amount")
private int amount;
// Setters, getters, constructor
Comparator<myClass > comp = Comparator.<myClass>comparing(myClass::getFrom)
.thenComparing(myClass::getTo)
.thenComparing(myClass::getWith)
.thenComparingInt(myClass::getAmount);
@Override
public int compareTo(myClass o) {
return comp.compare(this, o);
}
}
有人可以指出我在这里可能遗漏了什么吗?
好的,这里有几件事。首先,这是工作代码,主要只是删除了您提供的类型参数。
您可以这样做,因为系统会自动推断出它们。你只需要在它们不可推断时明确地做(你的 IDE 会告诉你)。 Java 文档中散布着大量关于类型推断的信息;例如https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
import java.util.Comparator;
public class MyClass implements Comparable<MyClass>{
private String from;
private String to;
public String getFrom() { return from; }
public String getTo() { return to; }
Comparator<MyClass> comp = Comparator.comparing(MyClass::getFrom)
.thenComparing(MyClass::getTo);
@Override
public int compareTo(MyClass o) {
return comp.compare(this, o);
}
}
其他一些对一般情况或 SO 有帮助以供将来参考的注释:
- class 名称中的首字母大写。
- 尝试将您的代码简化为 full/reproducible 示例。例如,这使用 2 个字段,它们都存在并且可以粘贴到 IDE 中。第一个问题使用了 4 个字段,其中大部分不存在。
Comparator::comparing 是一种通用方法,它采用用于提取要比较的值的函数。您将方法引用传递给 myClass::getFrom
方法,该方法 return 是 String
并将在 myClass
类型对象上调用(通过 Function::apply
)。这就是为什么你必须传递泛型类型 myClass
和 String
.
但是您可以忽略这些泛型类型,因为您将比较器分配给 Comparator<myClass> comp
变量,因此可以自动推断类型(也可以使用所用方法引用中的类型)。
让我们进一步看一下 Comparator::comparing(Function)
方法实现:
static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> var0) {
Objects.requireNonNull(var0);
return (Comparator)((Serializable)((var1x, var2x) -> {
return ((Comparable)var0.apply(var1x)).compareTo(var0.apply(var2x));
}));
}
此处 T
将是 myClass
,U
将是 String
。函数 var0
将采用 myClass
作为参数并将 return String
(因此对 myClass::getFrom
的方法引用将在这里起作用 - 通常它就像调用 getFrom
在 myClass
对象上)。实际上,如您所见,此方法将 return 一个 Comparator
作为 lambda 函数,它将使用函数 var0
从 var1x
和 var2x
中提取值(两者它们将是 myClass
类型)。对我来说,它看起来有点像闭包。
我正在尝试创建一个 class 可比较的实现。当所有 class 元素都是整数时,一切正常。当我使用 String 并使用 comparing
而不是 comparingInt
时,我收到以下错误。
Comparator 类型的泛型方法 comparing(Function) 的类型参数数量不正确;它不能用参数
参数化
类型myClass没有定义这里适用的getFrom(T)
public class myClass implements Comparable<myClass> {
@Column (name="From")
private String from;
@Column (name="To")
private String to;
@Column (name="With")
private String with;
@Column (name="amount")
private int amount;
// Setters, getters, constructor
Comparator<myClass > comp = Comparator.<myClass>comparing(myClass::getFrom)
.thenComparing(myClass::getTo)
.thenComparing(myClass::getWith)
.thenComparingInt(myClass::getAmount);
@Override
public int compareTo(myClass o) {
return comp.compare(this, o);
}
}
有人可以指出我在这里可能遗漏了什么吗?
好的,这里有几件事。首先,这是工作代码,主要只是删除了您提供的类型参数。
您可以这样做,因为系统会自动推断出它们。你只需要在它们不可推断时明确地做(你的 IDE 会告诉你)。 Java 文档中散布着大量关于类型推断的信息;例如https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
import java.util.Comparator;
public class MyClass implements Comparable<MyClass>{
private String from;
private String to;
public String getFrom() { return from; }
public String getTo() { return to; }
Comparator<MyClass> comp = Comparator.comparing(MyClass::getFrom)
.thenComparing(MyClass::getTo);
@Override
public int compareTo(MyClass o) {
return comp.compare(this, o);
}
}
其他一些对一般情况或 SO 有帮助以供将来参考的注释:
- class 名称中的首字母大写。
- 尝试将您的代码简化为 full/reproducible 示例。例如,这使用 2 个字段,它们都存在并且可以粘贴到 IDE 中。第一个问题使用了 4 个字段,其中大部分不存在。
Comparator::comparing 是一种通用方法,它采用用于提取要比较的值的函数。您将方法引用传递给 myClass::getFrom
方法,该方法 return 是 String
并将在 myClass
类型对象上调用(通过 Function::apply
)。这就是为什么你必须传递泛型类型 myClass
和 String
.
但是您可以忽略这些泛型类型,因为您将比较器分配给 Comparator<myClass> comp
变量,因此可以自动推断类型(也可以使用所用方法引用中的类型)。
让我们进一步看一下 Comparator::comparing(Function)
方法实现:
static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> var0) {
Objects.requireNonNull(var0);
return (Comparator)((Serializable)((var1x, var2x) -> {
return ((Comparable)var0.apply(var1x)).compareTo(var0.apply(var2x));
}));
}
此处 T
将是 myClass
,U
将是 String
。函数 var0
将采用 myClass
作为参数并将 return String
(因此对 myClass::getFrom
的方法引用将在这里起作用 - 通常它就像调用 getFrom
在 myClass
对象上)。实际上,如您所见,此方法将 return 一个 Comparator
作为 lambda 函数,它将使用函数 var0
从 var1x
和 var2x
中提取值(两者它们将是 myClass
类型)。对我来说,它看起来有点像闭包。