在值上对映射进行排序的通用方法

时间:2011-06-09 09:02:16

标签: java generics

我有一个小程序,应该根据它的值对地图进行排序。以下是我到目前为止的情况:

    public static <K, V extends Comparable< ? extends V>> Map<K, V> 
    sortByValues(final Map <K, V> mapToSort)
    {
        List<Map.Entry<K, V>> entries = 
            new ArrayList<Map.Entry<K, V>>(mapToSort.size());

        entries.addAll(mapToSort.entrySet());

        Collections.sort(entries, new Comparator<Map.Entry<K, V>>()
        {
            public int compare(
                               final Map.Entry<K, V> entry1, 
                               final Map.Entry<K, V> entry2)
            {
                return entry1.getValue().compareTo(entry2.getValue());
            }
        });

        Map<K, V> sortedMap = new LinkedHashMap<K, V>();

        for (Map.Entry<K, V> entry : entries)
        {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        return sortedMap; 
    }

我希望我的通用值V可以与 V或至少是V 的子类的任何内容相媲美。

我的代码片段出现以下错误:

public static <K, V extends Comparable< ? extends V>>
  

绑定不匹配:方法compareTo(?   扩展V)类型V不适用   对于论证(V)。通配符   参数?延伸V没有更低   绑定,可能实际上更多   限制比参数V

如何限制更多?

如果我将声明更改为:

public static <K, V extends Comparable< ? super V>>

然后没有错误。但这不是我想要的。

我的一个解决方法是,我可以将声明更改为:

public static <K, V extends Comparable<V>>

但是这样做我失去了灵活性,因为我无法传递一个Map,它的值实现了Comparable与它自己的子类。

为这么长的问题道歉。提前谢谢。

3 个答案:

答案 0 :(得分:4)

我认为你的第二个选择,即

public static <K, V extends Comparable<? super V>>

是通往的方式。我认为这是因为你写的时候

public static <K, V extends Comparable<C extends V>>

你基本上说你希望能够V的任何实例与C 的任何实例进行比较。但是这里缺少的是,因为你想在内部调用Collections.sort(..),你还必须能够C的任何实例与V的任何实例进行比较。但是泛型不表达这一点,理所当然编译器会抱怨。

基本上,要排序某些值(至少使用Collections.sort(..)),它们必须相互可比较,但您设想的通用限制只能保证您可以在一个方向进行比较。

答案 1 :(得分:3)

  

实现与自身的子类Comparable。

这是“糟糕的设计”:作为一般规则,类不应该知道它们的子类。

您有什么用例?

我认为public static <K, V extends Comparable<V>>没问题。

答案 2 :(得分:0)

我认为您希望V成为某种类型的扩展。尝试在模板声明中添加临时类型T,如下所示:

public static <K, T extends Comparable<T>, V extends T> Map<K, V> 
    sortByValues(final Map <K, V> mapToSort)

其他一切都保持不变。如果你不是那个意思,那就是你的所有可比对象都将成为V的子类型,那么public static <K, V extends Comparable<V>>是有意义的,因为从V的角度来看,覆盖了比较的V的子类将会使用与V具有的compareTo方法相同的签名调用compareTo方法。即,V声明的compareTo方法将被调用(但它可能是V的子类中被重写的定义)。因此,V extends Comparable<V>就足够了。我希望我已经说清楚了。