37

如果 aHashMap的键是一个String[]数组:

HashMap<String[], String> pathMap;

您可以使用新创建的String[]数组访问地图,还是必须是同一个String[]对象?

pathMap = new HashMap<>(new String[]{"korey", "docs"}, "/home/korey/docs");
String path = pathMap.get(new String[]{"korey", "docs"});
4

9 回答 9

46

它必须是同一个对象。AHashMap比较键使用equals()和 Java 中的两个数组只有当它们是相同的对象时才相等。

如果你想要值相等,那么编写你自己的容器类来包装 a并为andString[]提供适当的语义。在这种情况下,最好使容器不可变,因为更改对象的哈希码会对基于哈希的容器类造成严重破坏。equals()hashCode()

编辑

正如其他人指出的那样,List<String>具有您似乎想要的容器对象的语义。所以你可以做这样的事情:

HashMap<List<String>, String> pathMap;

pathMap.put(
    // unmodifiable so key cannot change hash code
    Collections.unmodifiableList(Arrays.asList("korey", "docs")),
    "/home/korey/docs"
);

// later:
String dir = pathMap.get(Arrays.asList("korey", "docs"));
于 2013-05-30T14:45:01.807 回答
11

不,但您可以使用List<String>which 将按您的预期工作!

于 2013-05-30T14:50:07.417 回答
3

Java 中的数组使用Object'shashCode()并且不覆盖它(与equals()and相同toString())。所以不,你不能不使用数组作为 hashmap 键。

于 2013-05-30T14:47:24.440 回答
2

您不能使用纯 JavaArray作为HashMap. (嗯,你可以,但它不会按预期工作。)

但是您可以编写一个包装类,该类具有对 Array 的引用并且还覆盖hashCode()and equals()

于 2013-05-30T14:50:39.863 回答
1

Ted Hopp 是对的,它必须是同一个对象。

有关信息,请参阅此示例:

public static void main(String[] args) {
    HashMap<String[], String> pathMap;
    pathMap = new HashMap<String[], String>();
    String[] data = new String[]{"korey", "docs"};
    pathMap.put(data, "/home/korey/docs");
    String path = pathMap.get(data);
    System.out.println(path);
}

当您运行上述代码时,它将打印“文档”。

于 2013-05-30T14:48:53.240 回答
0

在大多数情况下,如果数组中的字符串不是病态的并且不包含逗号后跟空格的字符串,则可以将Arrays.toString()其用作唯一键。即你Map会是一个Map<String, T>。并且数组的获取/放置myKeys[]将是

T t = myMap.get(Arrays.toString(myKeys));

myMap.put(Arrays.toString(myKeys), myT);

显然,如果需要,您可以放入一些包装器代码。

一个很好的副作用是您的密钥现在是不可变的。当然,你改变你的数组 myKeys 然后尝试 a get(),你不会找到它。

字符串的散列是高度优化的。所以我的猜测是,这个解决方案虽然感觉有点慢和笨拙,但比使用不可变列表的@Ted Hopp 解决方案更快,内存效率更高(对象分配更少)。想想Arrays.toString()你的钥匙是否是独一无二的。如果没有,或者有任何疑问,(例如,String[] 来自用户输入),请使用 List。

于 2013-11-06T16:16:16.433 回答
0

Java 9开始,您可以使用Arrays::compare方法作为比较器来TreeMap比较数组的内容

Map<String[], String> map = new TreeMap<>(Arrays::compare);

String[] key1 = {"one", "two"};
String[] key2 = {"one", "two"};
String[] key3 = {"one", "two"};

map.put(key1, "value1");
map.put(key2, "value2");

System.out.println(map.size()); // 1
System.out.println(map.get(key1)); // value2
System.out.println(map.get(key2)); // value2
System.out.println(map.get(key3)); // value2

另请参阅:如何Set在 Java 中创建数组?

于 2021-06-12T18:57:00.827 回答
0

就像说的那样,您需要一个围绕您的数组的包装类来覆盖相等性和 hashCode。

例如

/** 
 * We can use this instance as HashKey,
 * the same anagram string will refer the same value in the map.
 */
class Anagram implements CharSequence {

    private final char[] anagram;

    public Anagram(String anagram) {

        this.anagram = anagram.toCharArray();
        Arrays.sort(this.anagram);
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Anagram that = (Anagram) o;
        return Arrays.equals(this.anagram, that.anagram);
    }

    @Override
    public int hashCode() {

        return Arrays.hashCode(this.anagram);
    }

    @Override
    public int length() {

        return anagram.length;
    }

    @Override
    public char charAt(int index) {

        return anagram[index];
    }

    @Override
    public CharSequence subSequence(int start, int end) {

        return new String(anagram).subSequence(start, end);
    }

    @Override
    public String toString() {

        return Arrays.toString(anagram);
    }
}

否则将您的地图声明为IdentityHashMap,然后用户知道我们需要为您的 CRUD 使用相同的实例。

于 2021-09-09T05:03:05.740 回答
-1

使用该Arrays实用程序及其提供的哈希码的运行示例:

String[] key1 = { "korey", "docs" };
String value1 = "/home/korey/docs";
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(Arrays.hashCode(key1), value1);
System.out.println(map);

{-1122550406=/home/korey/docs}

如果您只关注存储,则此方法很有用。使用可读(原始)密钥检索很简单:

String retrievedValue = map.get(Arrays.hashCode(key1));
System.out.println(retrievedValue);

/home/korey/文档

于 2020-01-24T01:14:48.357 回答