【问题标题】:How to insert array into hashtable w/o initializing in Java?java - 如何在不使用Java初始化的情况下将数组插入哈希表?
【发布时间】:2012-07-20 15:00:09
【问题描述】:

我有一个 hashmap 初始化如下:

Hashmap<String[][], Boolean> tests = new Hashmap<String [][], Boolean>();

我想在不初始化密钥的情况下插入测试:

tests.put({{"a"}, {"a"}}, true);

但是,Java 似乎不允许我这样做。如果我这样做,它会起作用:

String[][] hi = {{"a"}, {"a"}};
tests.put(hi, true);

有什么办法可以避免后者并让前者工作吗?

谁能解释这个错误背后的原因?

谢谢

【问题讨论】:

  • 感谢快速回答,我编辑了我的问题以询问此错误背后的原因,如果有人也愿意回答这个问题。
  • 仅供参考,首先你不能真正使用数组作为 HashMap 中的键——它将使用引用相等,而不是值相等。
  • 非常感谢,我想知道为什么它不起作用:)
  • 是的。最简单的解决方案通常是使用正确的equalshashCode 实现围绕数组创建一个包装类。

标签: java arrays hash initialization hashmap


【解决方案1】:

是的,你可以这样写:

tests.put(new String[][] {{"a"}, {"a"}}, true);

这通常被称为匿名数组即时数组。

【讨论】:

    【解决方案2】:

    在您的情况下,您将不得不使用

    tests.put(new String[][]{{"a"}, {"a"}}, true);
    

    因为你注意到{{"a"}, {"a"}}

    String[][] hi = {{"a"}, {"a"}};
    

    只能在创建对数组的引用时使用。

    【讨论】:

      【解决方案3】:

      你可以使用

      tests.put(new String[][]{{"hello", "goodbye"},{"hi", "bye"}}, true);
      

      【讨论】:

      • OP 想要二维字符串数组。
      • @JigarJoshi:差不多了,你还需要额外的[]s。 :)
      【解决方案4】:

      这几乎肯定不是你想要的。

      Java 中的数组从Object 获取它们的相等性和哈希码——也就是说,基于它们的引用标识。所以:

      String[] a = { "hello" }; // create one array
      String[] b = { "hello" }; // create a different array with the same contents
      assert a != b; // the two references are to different objects
      assert ! a.equals(b); // they're not equal
      assert a.hashCode() != b.hashCode(); // neither are their hashes (probably)
      

      ab 不相等,而且它们的哈希码几乎肯定不相等,因为它们是不同的对象。这意味着如果您使用数组作为哈希映射的键,您将无法使用键检索值,而是使用您创建它的确切键:任何其他数组都将具有不同的哈希码并且将不相等,因此不会被视为等效键。

      解决方案是将String[][] 替换为List&lt;List&lt;String&gt;&gt;。列表根据其内容定义相等和哈希码,因此包含[ "hello" ] 的列表等于包含[ "hello" ] 的任何其他列表:

      List<String> x = Arrays.asList("hello");
      List<String> y = Arrays.asList("hello");
      assert x != y; // the two lists are different objects
      assert x.equals(y); // but they're equal
      assert x.hashCode() == y.hashCode(); // and so are their hash codes
      

      现在您可以将列表用作键。请记住,一旦列表成为地图的键,就不允许更改值。这样做可能会破坏哈希映射,因为列表的哈希码会发生变化,但映射不会知道它,因此映射会在错误的哈希桶中查找它。

      这里最简单的选择是:

      1. 确保没有其他人引用同一个 List 对象并且可能会更改它
      2. 在将列表放入地图之前创建一个深层副本(即复制“内部”列表和“外部”列表)

      对于第二个选项,它会是这样的:

      // copy the outer list
      List<List<String>> outerCopy = new ArrayList<List<String>>( originalList );
      ListIterator<List<String>> listIterator = outerCopy.listIterator();
      while (listIterator.hasNext()) {
          // make a copy of the inner list
          List<String> innerCopy = new ArrayList<String>( listIterator.next() );
          listIterator.set(innerCopy);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        相关资源
        最近更新 更多