0

经过一段时间的研究和查找旧帖子后,我意识到当您在 Java 中使用字符串为键的 Hashmap 或 Hashtable 时,第一轮“散列”应用于每个字符串对象 hashCode(显然还有第二个散列应用于) 的结果的函数,int hashCode()默认情况下int hashCode()与其在内存中的调用者位置有某种关系(从我读到的内容)。话虽如此,如果我有一个带有开发人员定义的键类的映射,我读到我可以覆盖int hashCode()并使用我的对象的一些不同字段来为每个对象返回最独特的 int 可能。但是,请考虑下面包含原始类型数组的代码片段。

import java.util.HashMap;

public class test
{ 

    public static void main(String[] args) { 

        HashMap<char[], int[] > map = new HashMap<char[], int[]>();

        String s = "Hello, World";

        int x[] = { 1, 2, 3, 4, 5 };

        map.put( s.toCharArray(), x );

        x = map.get( s );

        for ( int i : x )
            System.out.print( i );
    } 
}

程序当然会从 a 崩溃,NullPointerException因为map.get( s );返回 null。我怀疑这种情况已经发生,因为map.put()和之间有两个不同的引用map.get()。我希望程序输出的是 1 2 3 4 5。

我的问题:如何让上面的代码片段通过键的值与键的引用来查找键?也就是说,我怎样才能让程序输出1 2 3 4 5?

编辑:我使用哈希图作为查找表。我正在从文件中读取字符串,需要一种快速的方法来确定我刚刚读入的字符串是否在表中。

4

4 回答 4

3

只需使用字符串作为地图的键。

HashMap<String, int[] > map = new HashMap<String, int[]>();
String key = "array1";
int x[] = { 1, 2, 3, 4, 5 };
map.put( key, x );

String 是不可变的,因此它是一个不错的选择作为映射的键。

添加另一个数组:

String key2 = "array2";
int x2[] = { 6, 7, 8, 9, 10 };
map.put( key2, x2 );

输出值:

x = map.get( key );
for ( int i : x )
    System.out.print( i + " " );
}

1 2 3 4 5

x = map.get( key2 );
for ( int i : x )
    System.out.print( i + " " );
}

6 7 8 9 10

于 2014-07-18T10:42:29.917 回答
2
  1. “在某处读到有 2 轮散列”。不。如果你想看看字符串是如何被散列的——去看看代码。
  2. 哈希映射的基本约定是,如果键具有相同的哈希并且它们的功能相等,它将检索项目equals。为什么你认为它char[]有一个覆盖equals,允许它正确地与字符串进行比较?甚至彼此之间?它不会覆盖equals,并且只有在它是同一个实例时才会返回true。
  3. 您正在使用数组作为键。这是可能的,但大多数高级开发人员会为此大喊大叫。没有比较它们的好方法: Object.equals (它们默认使用)意味着您无法复制数组 - 您必须使用完全相同的 object。使用 Arrays.equals (或类似的方法来比较内容)将意味着您将可变对象作为键 - BAD

根据您的评论,我了解您希望能够编辑字符串。在您将其放入地图之前,这很好。但是,当对象是映射中的键时,不要以可能更改哈希码或等于的方式更改对象。最好的方法是使用自定义对象。数组不适合这个。

如果您真的想在地图中动态更改值 - 使用 a BiMap(或自己做它做的forcePut事情)。

于 2014-07-18T10:54:11.440 回答
1

有很多方法可以做到这一点。您可以做的最小更改之一是char[]在调用之前简单地保存您的put(),并使用与以下参数相同的参数get()

char[] charArray = s.toCharArray();
map.put(charArray, x);
x = map.get(charArray);

这里重要的是您需要使用与以前相同的get()对象 put()

于 2014-07-18T10:42:23.173 回答
0

来自 Oracle 文档

public V get(Object key)

Returns the value to which the specified key is mapped, or null if this 
map contains no mapping for the key.
More formally, if this map contains a mapping from a key k to a value v 
such that (key==null ? k==null : key.equals(k)), then this method returns v; 
otherwise it returns null.

显然 s.equals(s.toCharArray()) 是错误的。他们甚至不是同一个班级。

但是,您可以将覆盖 equals() 的 Class 用作键,从而为您的案例返回 true。例如:

class MyCharArray {

   private char[] data;

   @Override
   public boolean equals(Object o) {
       if (o instanceOf String) {
           return data.equals(o.toCharArray);
       else {
           return false;
       }
   }

   ...
}
于 2014-07-18T10:49:15.983 回答