使用哈希码比较Map的关键元素

时间:2015-01-29 16:39:53

标签: java hashmap hashcode

我想使用HashCode比较地图的元素。是否可以这样做?

例如,我的HashMap看起来像这样:

HashMap<Integer,String> map=new HashMap<Integer, String>();
map.put(123,"ABC");
map.put(345,"Abc");
map.put(245,"abc");

我假设所有值必须具有相同的哈希码,以便我可以比较它们并获取所有键(123,345,245)。

我的假设是否正确?我可以使用哈希码来比较密钥吗?

4 个答案:

答案 0 :(得分:1)

您无需明确地执行此操作。

HashMap已经散列了它的密钥。

只需调用:map.keySet()即可获得密钥的Set

示例

HashMap<Integer,String> map = new HashMap<Integer, String>();
map.put(123,"ABC");
map.put(345,"Abc");
map.put(245,"abc");
System.out.println(map.keySet());

<强>输出

[245, 123, 345]

如果我需要排序的键(此处,按照其自然顺序)

两种解决方案。

  1. 使用TreeMap代替

    Map<Integer,String> map = new TreeMap<Integer, String>();

  2. 稍后将Set包裹在TreeSet左右

    System.out.println(new TreeSet<Integer>(map.keySet()));

答案 1 :(得分:1)

在我看来,你真正想要的是使名称成为地图的关键,并且相应的电话号码设定值。

此外,您希望您的密钥不区分大小写...大小写不同的字符串实例将具有不同的哈希代码,因此您不能在此处将它们用作密钥本身。您需要做的是在访问地图时将名称转换为规范形式(例如全部小写),以便大小写中的差异不再相关。

有几种方法可以解决这个问题......扩展HashMap以满足您的需求是一种优雅的方式。

最好使用String来存储电话号码,因为它们通常包含非数字字符......

public class PhoneBook extends HashMap<String,Set<String>> {

   public PhoneBook() { }

   public PhoneBook(int initialCapacity) { super(initialCapacity); }

   // Use this method to add numbers to the phone-book
   // returns true if the phone directory changed as a result of the call.
   public boolean add(String name, String number) {
        String canonicalName = name.toLowerCase();
        Set<String> existingNumbers = super.get(name);
        if (existingNumbers == null) 
            super.put(canonicalName,existingNumbers = new HashSet<>(10)); 
        // give an estimate capacity per name, in this example 10.           
        return existingNumbers.add(number);
   }  

   @Override
   public Set<String> put(String name, Set<String> numberSet) {
        throw new UnsupportedOperationException("you must use add(String) to add numbers");
   }

   @Override
   public Set<String> get(String name) {
       String canonicalName = name.toLowerCase();
       Set<String> existingNumbers = super.get(canonicalName);
       return existingNumbers == null ? Collections.EMPTY_SET : existingNumbers;
   }

} 

您可能需要覆盖Map / Hash映射中的其他一些操作,以确保保持一致性。

答案 2 :(得分:0)

你的假设不正确。

来自Wikipedia

  

在Java编程语言中,每个类都隐式或显式   提供了一个hashCode()方法,它消化存储在一个中的数据   将类的实例转换为单个哈希值( 32位签名   整数)。存储时或其他代码使用此哈希   操纵实例(...)。 此属性对此很重要   哈希表和存储的其他数据结构的性能   组中的对象(“桶”)基于其计算的哈希值。

现在,您的每个实例都有一个哈希码,该哈希码可以与其他对象的哈希码相同或不同。 Map集合使用密钥的哈希码(通过hashcode()方法),以便在内部将数据存储在存储桶中(如果您需要更多详细信息,请查看here)。< / p>

如上所述,这并不意味着存储在同一个存储桶中的所有对象确实具有相同或不同的哈希码。

更新:为什么要使用哈希码比较对象?如果你想比较地图的键或值,我建议你通过迭代它们的集合来进行价值或对象比较(你可以分别通过map.keySet()map.values()得到它们)和使用哈希码。你不能确定hashCode()的值对于不同的对象是否相同或不同。

答案 3 :(得分:0)

有不同的方法来实现这一点,即单键 - &gt;多值

  1. 使用Hashmap和arraylist combine
  2. 使用guava集合的多图
  3. 使用apache commons collection提供的multimap
  4. 以下是详细说明: http://java.dzone.com/articles/hashmap-%E2%80%93-single-key-and