【问题标题】:can i keep duplicate contains of key in Map我可以在地图中保留重复包含的键吗
【发布时间】:2018-01-16 21:42:49
【问题描述】:

为什么我可以在 Map 中保留重复的包含作为键, 我对地图的心意是:它不包含重复的键

import java.util.LinkedHashMap;

import java.util.HashMap;

class LinkedHasMapDemo
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
    LinkedHashMap l = new LinkedHashMap();
    //{116=kumar, 116=kumar, kumar=kumar, 117=Ram charan, 105=Yash}
    //HashMap l = new HashMap(); 
    //{116=kumar, 117=Ram charan, 116=kumar, kumar=kumar, 105=Yash}
    l.put("116","kumar");       //key is String Object
    l.put(116,"kumar");         //key is Integer Object
    l.put("kumar","kumar");
    l.put(117,"Ram charan");
    l.put(105,"Yash");
    System.out.println(l);  
}
}

但是在这个例子中,我能够在 LinkedHashMap 和 HashMap 中保留重复的键

【问题讨论】:

  • 您的示例代码没有重复键。另外,don't use raw types。这可能就是让你感到困惑的地方。
  • 你认为重复键是什么? "116"116 不相等。

标签: java dictionary collections


【解决方案1】:

你是对的,Map 确实不保存重复的键(这只适用于键,值可以相等)。如果您将值放在已添加的键下,则先前的值将被覆盖。因此考虑以下示例:

HashMap<String, Integer> map = new HashMap<>();

map.put("key", 1);
System.out.println(map.get("key")); // Outputs 1
System.out.println(map.size()); // Outputs 1

map.put("key", 2);
System.out.println(map.get("key")); // Outputs 2
System.out.println(map.size()); // Still outputs 1

您的反例的问题在于您的地图中实际上没有重复项

你把116(一个intInteger在拳击之后)和"116"(一个String)。由于两者都属于不同类型,地图将它们区分开来,因此它们是不同的对象。考虑下面的例子

HashMap<Object, Integer> map = new HashMap<>();

map.put("116", 1);
System.out.println(map.size()); // Outputs 1

map.put(116, 2);
System.out.println(map.size()); // Now outputs 2

System.out.println("116".equals(116)); // Outputs false

一般来说,您永远不应该使用 raw-types,即使用 HashMap 而不指定要使用的泛型类型,例如 HashMap&lt;String, Integer&gt;。如果您不指定任何内容,它将使用HashMap&lt;Object, Object&gt;。通过它,它允许将每个Object 放入地图中。在许多情况下,您可以并且希望仅将其限制为特定类型。

【讨论】:

    【解决方案2】:

    尝试以下方法:

    String s123="123";
    Integer i123=123;
    System.out.println(s123.hashCode());
    System.out.println(i123.hashCode());
    System.out.println(i123.equals(s123)); // you can try s123.equals(i123) too
    

    您甚至可以在线测试它,只需将这些行复制/键入到http://www.javarepl.com/term.html - 您会看到 String 的哈希码为 48690,Integer 的哈希码为 123,并且它们不认为彼此相等。
    (当然它也适用于 116,只是我在输入这个答案时没有那个数字)

    【讨论】:

      【解决方案3】:

      您没有重复项。 IntegerString 对象不是同一类型,因此“116”和 116 不相等,它们具有不同的哈希码

      相同的对象在运行的进程中必须具有相同的哈希码

      在equals方法中,如果两个对象的类型不相等,会返回false,请检查Integer equals植入

          public boolean equals(Object obj) {
          if (obj instanceof Integer) {
              return value == ((Integer)obj).intValue();
          }
          return false;
      }
      

      对于哈希码,在您的情况下它们也不相等:

      如何计算字符串哈希码:

       public int hashCode() {
          int h = hash;
          if (h == 0 && value.length > 0) {
              char val[] = value;
      
              for (int i = 0; i < value.length; i++) {
                  h = 31 * h + val[i];
              }
              hash = h;
          }
          return h;
      }
      

      对于Integer,哈希码是相同的整数值,所以在您的情况下,Integer 实例将是 116,所以它们永远不会相同。

      请避免使用原始类型,即使用 HashMap 而不指定泛型类型,请阅读本文what-is-a-raw-type-and-why-shouldnt-we-use-it了解更多详情

      【讨论】:

      • 即使它们具有相同的哈希码,它们也会被认为是不同的。
      • 但哈希码在这种情况下不相关,也没有理由说明它是如何计算的。您解释它的方式可能令人困惑,并暗示哈希码必须不同才能被视为不同的键。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多