比较HashMap和Objects

时间:2011-12-16 12:45:53

标签: java hashmap

我有一个hashmap<CustomObject,Integer>,我想比较每个条目中的整数(值)。所以,基本上我想按照Integer值按降序排序我的值。我有一个Comparator,其中包含以下内容......

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传递给TreeMap .. 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值按降序对我的集合进行排序。

6 个答案:

答案 0 :(得分:5)

您需要更改比较器以比较CustomObject,而不是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));

答案 1 :(得分:1)

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

构建树时必须指定比较器。否则,它假定您的密钥是可比较的(并且它们不是)

check this answer用于根据值对地图进行排序。

答案 2 :(得分:1)

这种方法存在一些问题。

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

您最好从List<Entry<CustomObject,Integer>>创建一个map.entrySet(),您可以对其进行排序,因为这样可以复制并订购。

答案 3 :(得分:1)

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

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

这也会告诉您,您的Compare类需要实现Comparator<CustomObject>而不是Comparator<Integer>

另一个问题是你的比较器没有实现正确的语义。如果arg1&lt;比较方法应该返回-ve数字。 arg2,如果arg1 = arg2则为零,如果arg1> gt,则为+ ve编号; ARG2; e.g。

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

即使这是狡猾的:

  • 如果映射到同一整数的任何两个CustomObject实例将被视为相等,则您将无法在TreeMap中同时拥有两个(不同)键。

  • 如果mapone two中没有条目,您的比较器将抛出NPE。

答案 4 :(得分:1)

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

答案 5 :(得分:0)

首先,密钥应该是Integer,值应该是CustomObject,然后可以根据比较器对HashMap进行排序。但是默认情况下,HashMap或者如果你想对CustomObject进行排序,那么你必须使CustomObject实现Comparable并在其中编写compare方法,这将使HashMap基于CustomObject进行排序。如果你已经理解了这一点。并想尝试自己的尝试。或者如果你想让我用一个例子来解释我可以做到。

问题很混乱。