Java Hashmap实现中的问题

Java Hashmap实现中的问题,java,string-hashing,Java,String Hashing,在做了一段时间的研究并查找了一些旧帖子之后,我意识到,当您在Java中使用以字符串为键的Hashmap或Hashtable时,第一轮哈希将应用于每个字符串对象hashCode(显然还有第二个哈希函数应用于int hashCode())的结果,其中默认情况下,int hashCode()与它的调用者在内存中的位置(从我读到的内容)有一些关系。话虽如此,如果我有一个带有开发人员定义的键类的映射,我读到我可以重写int hashCode(),并使用对象的一些不同字段为每个对象返回尽可能唯一的int。但

在做了一段时间的研究并查找了一些旧帖子之后,我意识到,当您在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 );
    } 
}
import java.util.HashMap;
公开课考试
{ 
公共静态void main(字符串[]args){
HashMap=newHashMap();
String s=“你好,世界”;
int x[]={1,2,3,4,5};
map.put(s.toCharArray(),x);
x=map.get(s);
for(int i:x)
系统输出打印(一);
} 
}
程序因
NullPointerException
崩溃,当然是因为
map.get返回null。我怀疑这是因为
map.put()
map.get()
之间存在两种不同的引用。我希望程序输出的是123445

我的问题是:如何让上面的代码片段通过键的值与键的引用来查找键?也就是说,如何让程序输出12345

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

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


这里重要的一点是,您需要使用相同的对象来
get()
,就像您过去使用
put()

的方法一样。您可以做的最小更改之一是,在调用
put()
之前,只需保存
char[]
,并使用与
get()
相同的参数:


这里重要的一点是,您需要使用相同的对象来
get()
,就像您过去使用
put()

一样,只需使用字符串作为映射的键即可

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

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

123445

给予

678910


只需使用字符串作为映射的键

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

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

123445

给予

678910


来自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(),在您的情况下返回true。 例如:

class MyCharArray {

   private char[] data;

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

   ...
}

来自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(),在您的情况下返回true。 例如:

class MyCharArray {

   private char[] data;

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

   ...
}
  • “在某个地方读到有两轮散列”。不,如果你想知道字符串是如何散列的,去看看代码
  • 散列映射的基本约定是,如果键具有相同的散列并且通过其
    equals
    函数相等,则它将检索项。为什么您认为
    char[]
    有一个重写的
    equals
    ,允许它正确地将自身与字符串进行比较?甚至在彼此之间?它不会覆盖equals,并且仅当它是同一实例时才会返回true
  • 您正在对键使用数组。这是可能的,但大多数高级开发人员会为此向你大喊大叫。没有比较它们的好方法:Object.equals(它们默认使用)意味着您无法复制数组-您必须使用完全相同的对象。使用Arrays.equals(或类似的方法来比较内容)将意味着您将可变对象作为键-
  • 根据您的评论,我理解您希望能够编辑字符串。在你把它放到地图上之前没关系。但是当对象是映射中的键时,不要以可能更改哈希代码或相等值的方式更改对象。最好的方法是使用自定义对象。阵列不适用于此

    如果您真的想在地图中动态更改值,请使用
    BiMap
    (或者自己执行
    forcePut
    中的操作)

  • “在某个地方读到有两轮散列”。不,如果你想知道字符串是如何散列的,去看看代码
  • 散列映射的基本约定是,如果键具有相同的散列并且通过其
    equals
    函数相等,则它将检索项。为什么您认为
    char[]
    有一个重写的
    equals
    ,允许它正确地将自身与字符串进行比较?甚至在彼此之间?它不会覆盖equals,并且仅当它是同一实例时才会返回true
  • 您正在对键使用数组。这是可能的,但大多数高级开发人员会为此向你大喊大叫。没有比较它们的好方法:Object.equals(它们默认使用)意味着您无法复制数组-您必须使用完全相同的对象。使用Arrays.equals(或类似的方法来比较内容)将意味着您将可变对象作为键-
  • 根据您的评论,我理解您希望能够编辑字符串。在你把它放到地图上之前没关系。但是当对象是映射中的键时,不要以可能更改哈希代码或相等值的方式更改对象。最好的方法是使用自定义对象。阵列不适用于此

    如果你真的想