2011-12-16 108 views
1

我有hashmap<CustomObject,Integer>,我想比较每个条目中的整数(值)。所以,基本上我想按降序排列我的值Integer的值。我有一个Comparator它由以下部分组成...将HashMap与对象比较

class Compare implements Comparator<Integer>{ 
    Map<CustomObject,Integer> map; 
    /** 
    * Constructs our map 
    * @param map map to be sorted. 
    */ 
    public Compare(Map<CustomObject,Integer> map){ 
     this.map = map; 
    } 
    /** 
    * Performs the comparison between two entries. 
    */ 
    public int compare(Integer one, Integer two){ 
     if(map.get(one) <= map.get(two)){ 
      return 1; 
     }else{ 
      return 0; 
     } 
    } 
} 

我通过我的Hashmap成树形图通过调用下面的代码行.. Tmap.putAll(Hmap);。凡TMAP和HMAP被定义为:当我运行我的代码

private HashMap<CustomObject,Integer> Hmap; 
private TreeMap<CustomObject,Integer> Tmap; 

我得到的错误Exception in thread "main" java.lang.ClassCastException: CustomObject cannot be cast to java.lang.Comparable

当我试图从我的排序列表中提取一个值时,异常似乎会被调用。像这样......

TreeMap<CustomObject,Integer> sorted = Tmap.putAll(hmap); 
sorted.get(o); 

其中o是CustomObject。

我想我误解了比较器的工作原理..我做错了什么?我如何比较两个整数值?

编辑

只是为了澄清什么,我实际上是试图做...

我想比较其链接到CustomObject整数。我无法使整数的关键,因为这些整数可能不是唯一的。我想对它们进行比较,因为我想根据它们的Integer值以降序对我的集合进行排序。

+0

哪里是抛出异常的代码? – SJuan76 2011-12-16 12:50:07

+0

问题是比较器的地图比较键而不是值。除了执行反向映射外,我没有看到任何解决方案,然后继续,然后将结果插入到LinkedHashMap中。不是你想要的,我希望... – fge 2011-12-16 12:52:02

回答

5

你需要改变你的比较来比较CustomObject S,不Integers

class Compare implements Comparator<CustomObject>{ 
    Map<CustomObject,Integer> map; 
    /** 
    * Constructs our map 
    * @param map map to be sorted. 
    */ 
    public Compare(Map<CustomObject,Integer> map){ 
     this.map = map; 
    } 
    /** 
    * Performs the comparison between two entries. 
    */ 
    public int compare(CustomObject left, CustomObject right){ 
     return map.get(left).compareTo(map.get(right)); 
    } 
} 

然后,你需要告诉TreeMap使用您的比较:

private Map<CustomObject,Integer> Tmap = 
    new TreeMap<CustomObject,Integer>(new Compare(HMap)); 
0

第一薄的是,键应该是Integer,值应该是CustomObject,然后可以根据比较器对HashMap进行排序。但默认情况下HashMap的,或者如果你婉排序CustomObject那么你必须做出CustomObject实现可比谱写比较方法,这将使HashMap的排序基于CustomObject。如果你已经理解了这一点。并想尝试你的自我尝试。或者如果你想让我解释一个例子,我可以做到这一点。

问题很混乱。

1
new TreeMap<..>(new Compare<..>(map)) 

您必须在构建树时指定比较器。否则,它假设你的钥匙是可比的(他们并不)

check this answer进行排序基于值的地图。

1

这种方法有一些问题。

  • TreeMap忽略重复项(当compareTo返回0时)在你的情况下,它只会增加递减递减的整数值。您可以修复它,以便数字可以按任意顺序排列,但它仍会删除具有重复值的任何条目。
  • compareTo中使用的字段不能更改或将损坏集合。
  • 您需要知道整个密钥才能查找值。在这种情况下,您需要知道在这种情况下的值,以查看它可能不是非常有用的。

您是关创建从map.entrySet(),您可以排序List<Entry<CustomObject,Integer>>更好,因为这允许重复并且是有序的。

1

我认为问题在于您使用的是错误的TreeMap构造函数。您正在使用的那个要求所有密钥都是实现Comparable的类的实例。您的CustomObject没有。您应该使用带有Comparator参数的构造函数;例如

TreeMap<CustomObject,Integer> tmap = 
    new TreeMap<CustomObject,Integer>(new Compare()); 

这也将告诉你,你的比较类需要实现Comparator<CustomObject>Comparator<Integer>

另一个问题是你的比较器没有实现正确的语义。如果arg1 < arg2,比较方法应该返回一个-ve数字,如果arg1 = arg2则返回零,如果arg1> arg2则返回一个+ ve数字;例如

public int compare(CustomObject one, CustomObject two){ 
    return Integer.compare(map.get(one), map.get(two)); 
} 

即使这是狡猾的:

  • 如果映射到相同的整数任何两个CustomObject情况下,将被视为平等的,你就不能兼得的(不同)键在TreeMap中。

  • 如果map中没有输入onetwo,那么您的比较器将抛出NPE。

1

我会建议使用由整数索引的多图。如果您需要保留按对象查找这些对的功能,则可以维护这两个映射。 Java没有提供multimap,但有一些简单的解决方案。 HereMap<Integer,List<Object>>的示例(向下滚动到multimaps部分)。