سؤال

Background

Create a Map that can be sorted by value.

Problem

The code executes as expected, but does not compile cleanly:

http://pastebin.com/bWhbHQmT

public class SortableValueMap<K, V> extends LinkedHashMap<K, V> {
  ...
  public void sortByValue() {
      ...
      Collections.sort( list, new Comparator<Map.Entry>() {
          public int compare( Map.Entry entry1, Map.Entry entry2 ) {
            return ((Comparable)entry1.getValue()).compareTo( entry2.getValue() );
          }
      });
  ...

The syntax for passing Comparable as a generic parameter along to the Map.Entry<K, V> (where V must be Comparable?) -- so that the (Comparable) typecast shown in the warning can be dropped -- eludes me.

Warning

Compiler's cantankerous complaint:

SortableValueMap.java:24: warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable

   return ((Comparable)entry1.getValue()).compareTo( entry2.getValue() );

Question

How can the code be changed to compile without any warnings (without suppressing them while compiling with -Xlint:unchecked)?

Related

Thank you!

هل كانت مفيدة؟

المحلول

Declare the V type to extend the Comparable<V> interface. That way, you can remove the cast of the Map.Entry objects down to (Comparable) and use the inferred type instead:

public class SortableValueMap<K, V extends Comparable<V>>
             extends LinkedHashMap<K, V> {

....

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

نصائح أخرى

The value should be a subclass of comparable.

SortableValueMap<K, V extends Comparable>

Try the above.

The syntax for passing Comparable as a generic parameter along to the Map.Entry (where V must be Comparable?) -- so that the (Comparable) typecast shown in the warning can be dropped -- eludes me.

How about:

public class SortableValueMap <K, V extends Comparable<V>> extends LinkedHashMap<K, V> { 
  ...
    Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
        public int compare(Map.Entry<K, V> entry1, Map.Entry<K, V> entry2) {
            return (entry1.getValue()).compareTo(entry2.getValue());
        }
    });

but this may be better, depending on your intent:

public class SortableValueMap <K, V extends Comparable<? super V>> extends LinkedHashMap<K, V> { ...

See http://download.oracle.com/javase/tutorial/extra/generics/morefun.html

It isn't necessary that T be comparable to exactly itself. All that's required is that T be comparable to one of its supertypes. This give us:

public static <T extends Comparable<? super T>>  max(Collection<T> coll)

... This reasoning applies to almost any usage of Comparable that is intended to work for arbitrary types: You always want to use Comparable <? super T> . ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top