Cro*_*ode 114 java hash hashmap hashcode
我有一个整数的2D数组.我希望将它们放入HashMap中.但我想基于Array Index访问HashMap中的元素.就像是:
对于A [2] [5],map.get(2,5)
它返回与该键相关联的值.但是如何使用一对键创建hashMap?或者一般来说,多个键:Map<((key1, key2,..,keyN), Value)
我可以使用get(key1,key2,... keyN)访问元素.
编辑:发布问题3年后,我想补充一点
我遇到了另一种方式NxN matrix
.
数组索引,i
和j
可被表示为一个单一的key
方式如下:
int key = i * N + j;
//map.put(key, a[i][j]); // queue.add(key);
Run Code Online (Sandbox Code Playgroud)
并且可以通过key
以下方式从这些指数中恢复指数:
int i = key / N;
int j = key % N;
Run Code Online (Sandbox Code Playgroud)
Tom*_*icz 184
有几种选择:
Map<Integer, Map<Integer, V>> map = //...
//...
map.get(2).get(5);
Run Code Online (Sandbox Code Playgroud)
public class Key {
private final int x;
private final int y;
public Key(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key key = (Key) o;
return x == key.x && y == key.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
实施equals()
并hashCode()
在这里至关重要.然后你只需使用:
Map<Key, V> map = //...
Run Code Online (Sandbox Code Playgroud)
和:
map.get(new Key(2, 5));
Run Code Online (Sandbox Code Playgroud)
Table
来自番石榴Table<Integer, Integer, V> table = HashBasedTable.create();
//...
table.get(2, 5);
Run Code Online (Sandbox Code Playgroud)
Table
使用下面的地图.
请注意,特殊Key
类是唯一可扩展到n维的方法.您可能还会考虑:
Map<List<Integer>, V> map = //...
Run Code Online (Sandbox Code Playgroud)
但从性能角度来看,这是可怕的,以及可读性和正确性(没有简单的方法来强制列表大小).
也许看看Scala,你有元组和case
类(用Key
一行代替整个班级).
chr*_*xle 22
当您创建自己的密钥对对象时,您应该面对一些事情.
首先,您应该了解实施hashCode()
和equals()
.你需要这样做.
其次,在实施时hashCode()
,请确保您了解其工作原理.给定的用户示例
public int hashCode() {
return this.x ^ this.y;
}
Run Code Online (Sandbox Code Playgroud)
实际上是你可以做的最糟糕的实现之一.原因很简单:你有很多平等的哈希!并且hashCode()
应该返回往往很少见的int值,这是最好的唯一值.使用这样的东西:
public int hashCode() {
return (X << 16) + Y;
}
Run Code Online (Sandbox Code Playgroud)
这很快并且返回-2 ^ 16和2 ^ 16-1(-65536到65535)之间的键的唯一哈希值.几乎适用于任何情况.很少有人超出这个范围.
第三,实现时equals()
也知道它的用途,并了解如何创建密钥,因为它们是对象.通常你会做不必要的if语句,因为你总是会得到相同的结果.
如果您创建这样的键:map.put(new Key(x,y),V);
您永远不会比较键的引用.因为每次你想访问地图,你会做类似的事情map.get(new Key(x,y));
.因此,您equals()
不需要像这样的声明if (this == obj)
.它永远不会发生.
而不是if (getClass() != obj.getClass())
在你equals()
更好的使用if (!(obj instanceof this))
.它甚至对子类也有效.
所以你唯一需要比较的就是X和Y.所以equals()
在这种情况下最好的实现是:
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
所以最后你的关键类是这样的:
public class Key {
public final int X;
public final int Y;
public Key(final int X, final int Y) {
this.X = X;
this.Y = Y;
}
public boolean equals (final Object O) {
if (!(O instanceof Key)) return false;
if (((Key) O).X != X) return false;
if (((Key) O).Y != Y) return false;
return true;
}
public int hashCode() {
return (X << 16) + Y;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以提供维度索引X
和Y
公共访问级别,因为它们是最终的并且不包含敏感信息.在转换为a 时,我不能100%确定private
访问级别是否在任何情况下都能正常工作.Object
Key
如果你对决赛感到好奇,我会宣布任何事情都是最终的,在实例化时设置的值并且永远不会改变 - 因此它是一个对象常量.
您不能拥有包含多个键的哈希映射,但您可以拥有一个以多个参数作为键的对象.
创建一个名为Index的对象,该对象采用x和y值.
public class Index {
private int x;
private int y;
public Index(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int hashCode() {
return this.x ^ this.y;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Index other = (Index) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
然后让你HashMap<Index, Value>
得到你的结果.:)
Java 7+ 包含一个新Map.Entry<K,V>
类,您可以将其用作地图的键(或集合的条目)。Java 9+ 还包含一种Map.entry(K k, V v)
轻松创建新Map.Entry
对象的方法。
用法:
Map<Map.Entry<Integer,Integer>, Integer> map = new HashMap<>();
map.put(Map.entry(1, 2), 0);
Run Code Online (Sandbox Code Playgroud)
Pair<K, V>
javafx.util中也有
Map<Pair<Integer,Integer>, Integer> map = new HashMap<>();
map.put(new Pair(1, 2), 0);
Run Code Online (Sandbox Code Playgroud)
两种可能性。使用组合键:
class MyKey {
int firstIndex;
int secondIndex;
// important: override hashCode() and equals()
}
Run Code Online (Sandbox Code Playgroud)
或者地图的地图:
Map<Integer, Map<Integer, Integer>> myMap;
Run Code Online (Sandbox Code Playgroud)