这是一个很难解决的问题。我在使用varargs和仿制药之间有冲突。以下是给定的代码:
public class MyObject implements Comparable<MyObject>
{
private String name;
private int index;
@Override
public int compareTo(MyObject o)
{
if (name.compareTo(o.name) != 0)
return name.compareTo(o.name);
return ((Integer) index).compareTo(o.index);
}
}我希望compareTo方法使用多个比较条件。如果字符串相同,则使用ints代替。我想说的是通常的情况。
我很乐意创建一个静态方法来处理这个问题。我希望新方法chainedCompare的调用如下:
public int compareTo(MyObject o)
{
return chainedCompare(this, o, myO -> myO.name, myO -> myO.index);
}lambdas是Java 8接口函数的变体。所以首先我写了这样的方法:
public static <T, C extends Comparable<C>> int chainedCompare(T object1, T object2, Function<T, C>... comparisons)
{
int compareValue = 0;
for (Function<T, C> comparison : comparisons)
{
compareValue = comparison.apply(object1).compareTo(comparison.apply(object2));
if (compareValue != 0)
break;
}
return compareValue;
}但我没有考虑到,在这种情况下,对于varargs数组中的所有Function<T, C>比较,泛型类型C必须是相同的类型。正如您在上面看到的,我希望使用不同的比较器(例如,示例中的String和Integer )。
然后,我将其修改为这个版本:
public static <T> int chainedCompare(T object1, T object2, Function<T, ? extends Comparable<?>>... comparisons)
{
int compareValue = 0;
for (Function<T, ? extends Comparable<?>> comparison : comparisons)
{
compareValue = comparison.apply(object1).compareTo(comparison.apply(object2));
if (compareValue != 0)
break;
}
return compareValue;
}此处将C类型替换为通配符。虽然方法调用现在可以工作,但是由于compareTo的通配符类型参数,方法本身不编译。
因此,一方面,函数接口需要固定的泛型类型(扩展可比较),另一方面,我需要不同(第二)泛型类型的函数接口,通常可以设置通配符。如何解决这个问题?
我唯一的要求是,我可以像使用未定义的比较条件那样简单地调用静态方法。
根据Tunaki的建议,我对该方法进行了如下修改,该方法可按需要使用:
@SuppressWarnings("raw-types")
public static <T> int chainedCompare(T object1, T object2, Function<T, ? extends Comparable>... comparisons)
{
return Arrays.stream(comparisons)
.map(Comparator::comparing)
.reduce(Comparator::thenComparing)
.map(c -> c.compare(object1, object2))
.orElse(0);
}
public int compareTo(MyObject o)
{
return chainedCompare(this, o, myO -> myO.name, myO -> myO.index);
}发布于 2016-03-10 12:56:08
与其使用Comparable,不如使用Comparator
public static <T> int chainedCompare(T object1, T object2, Comparator<T>... comparators) {
int compareValue = 0;
for (Comparator<? super T> comparator : comparators) {
compareValue = comparator.compare(object1, object2);
if (compareValue != 0)
break;
}
return compareValue;
}您还可以使用thenComparing将所有比较器链接在一起,并且
@SafeVarargs
public static <T> int chainedCompare(T object1, T object2, Comparator<T>... comparators) {
return Arrays.stream(comparators)
.reduce(Comparator::thenComparing)
.map(c -> c.compare(object1, object2))
.orElse(0);
}然后,您可以通过使用Comparator或原语专门化comparingInt构造comparing(keyExtractor)对象来使用它。
@Override
public int compareTo(MyObject o) {
return chainedCompare(this, o,
Comparator.comparing(obj -> obj.name),
Comparator.comparingInt(obj -> obj.index)
);
}使用这种方法,您甚至可以质疑这种实用程序的存在,并且只需
@Override
public int compareTo(MyObject o) {
return Comparator.<MyObject, String> comparing(obj -> obj.name)
.thenComparingInt(obj -> obj.index)
.compare(this, o);
}https://stackoverflow.com/questions/35916874
复制相似问题