Java Hashmap实现中的问题
在做了一段时间的研究并查找了一些旧帖子之后,我意识到,当您在Java中使用以字符串为键的Hashmap或Hashtable时,第一轮哈希将应用于每个字符串对象hashCode(显然还有第二个哈希函数应用于Java Hashmap实现中的问题,java,string-hashing,Java,String Hashing,在做了一段时间的研究并查找了一些旧帖子之后,我意识到,当您在Java中使用以字符串为键的Hashmap或Hashtable时,第一轮哈希将应用于每个字符串对象hashCode(显然还有第二个哈希函数应用于int hashCode())的结果,其中默认情况下,int hashCode()与它的调用者在内存中的位置(从我读到的内容)有一些关系。话虽如此,如果我有一个带有开发人员定义的键类的映射,我读到我可以重写int hashCode(),并使用对象的一些不同字段为每个对象返回尽可能唯一的int。但
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(或类似的方法来比较内容)将意味着您将可变对象作为键-坏
根据您的评论,我理解您希望能够编辑字符串。在你把它放到地图上之前没关系。但是当对象是映射中的键时,不要以可能更改哈希代码或相等值的方式更改对象。最好的方法是使用自定义对象。阵列不适用于此
如果你真的想