答案: 感谢您的帮助!像大多数人一样,解决方案是创建一个新的2d int数组,并复制旧数组中的值。这是我做的功能,然后我可以将新板添加到hashmap中,作为新密钥。
void newboard(){
NewBoard = new int[N][N];
for(int n = 0; n < N; n++){
for(int i = 0; i < N; i++){
NewBoard[n][i] = CurrentBoard[n][i];
}
}
}
问题:
我有以下代码,它将一个3x3板和一个整数列表,特别是(f,g,h)放入一个hashmap。理事会CurrentBoard
是一个未解决的8难题。
public static HashMap<int[][], List<Integer>> map = new HashMap<>();
map.put(CurrentBoard, fgh);
我初始化了hashmap,对于程序的其余部分,我想迭代遍历地图,以获得我需要的板。地图的每个条目都将是&#39; 0
&#39;之后的8-puzzle board的特定状态。位置已被移动。
这是我这样做的方式。 &#39; cv&#39;变量只是选择最低的&#34; f&#34;值。
for(Map.Entry<int[][], List<Integer>> mapentry : map.entrySet()) {
if (cv > mapentry.getValue().get(0)) {
cv = mapentry.getValue().get(0);
CurrentBoard = mapentry.getKey();
fgh = mapentry.getValue();
}
}
现在,我已经在&#34; CurrentBoard
&#34;变量,我想移动&#39; 0
&#39;一排。所以我称之为这个功能:
void moveUp(){
NewBoard = CurrentBoard;
memory = NewBoard[ZeroPositionX][ZeroPositionY - 1];
NewBoard[ZeroPositionY- 1][ZeroPositionX] = 0;
NewBoard[ZeroPositionY][ZeroPositionX] = memory;
}
然后我做了一些(对于这个问题)不重要的检查,并重新计算此fgh
的{{1}}值。
然后,我继续使用
将NewBoard
和NewBoard
值一起放入fgh
hashmap
我的问题是,它取代了hashmap中的当前键。换句话说,它不是向hashmap添加键和值,而是替换已存在的键和值。我尝试过打印新电路板和当前电路板,以确保它们不同。
当我打印map.put(NewBoard, fgh);
的{{1}}时,它只会给我最新的条目。换句话说,董事会以及移动&{39; entrySet()
后的价值。
hashmap
为什么将新密钥和值添加到0
不起作用?
尾注:我是Java新手,因此其中一些可能不是最佳的。如有必要,我会尽力详细解释。
答案 0 :(得分:0)
您正在更改NewBoard
变量/数组的内容,但引用保持不变。因此,当您调用map.put(NewBoard, fgh);
时,密钥始终是相同的引用(在内存中考虑相同的地址,尽管每次都有不同的内容)。
如果要在地图中为每个电路板状态存储新条目,则每次都必须创建一个新数组并复制+更改其内容。
答案 1 :(得分:0)
问题是您正在修改您的HashMap密钥的 function init1() {
$('.makeMeDraggable').each(function(i) {
$(this).draggable({
revert: true,
delay: 100,
helper: "clone",
appendTo: 'body', //<-==This is what fixed it.
containment: "document"});
})}
,而不是创建一个新密钥。这是您的代码摘要(某些行被剪切):
int[][]
请注意,一般来说,修改地图中任意关键字的内容并不是一个好主意 - 它可能导致甚至比您所看到的更奇怪的行为。
另请注意,使用数组作为映射键通常是错误的 - 因为映射依赖于key1.equals(key2)的结果,并且对于任何Java数组CurrentBoard = mapEntry.getKey(); //here CurrentBoard points at the exact same object as the key in your map
NewBoard = CurrentBoard; //now NewBoard and CurrentBoard are both pointing at the same int[][]
NewBoard[a][b] = 0; //this updates that one object
NewBoard[c][d] = memory; //still updating the same object
map.put(NewBoard, fgh); //NewBoard is still the same object, so this is replacing the existing key
,a1, a2
仅限于a1.equals(a2)
(也就是说,它们是同一个数组)。例如:
a1 == a2
答案 2 :(得分:0)
问题是您正在修改相同的密钥,这将无法按预期工作。要获得“正确”的行为,您应该克隆密钥。由于您的密钥为int[][]
,因此您无需执行任何操作,只需拨打clone()
。
int[][] currentBoard = {{1, 2, 3}, {4, 5, 6}};
HashMap<int[][], String> map = new HashMap<int[][], String>();
map.put(currentBoard, "test1");
int[][] cloned = currentBoard.clone();
cloned[0][0] = 10;
map.put(cloned, "test2");
for(Map.Entry mapentry : map.entrySet()){
System.out.println(mapentry.getValue());
}
打印
test1
test2
如果您想使用自己创建的某个课程,则需要覆盖clone()
,请参阅Cloneable
重要的是要注意clone()只会克隆数组引用,而不是它的值。所以currentBoard[0].equals(cloned[0])
将是真的,但我认为这对你的案例没有任何影响。
另见关于克隆Java: recommended solution for deep cloning/copying an instance
的问题答案 3 :(得分:0)
更改int[][]
类型的地图关键字中的值不会改变其equals
和hashCode
方法的行为方式。这些是被调用以确定密钥在语义上是否相同的方法。
因此,要添加新密钥,您必须创建一个新密钥或使用具有不同equals
/ hashCode
逻辑的正确类。
要创建新密钥,您可以使用clone()
:
void moveUp() {
NewBoard = new int[3][3];
NewBoard[0] = CurrentBoard[0].clone();
NewBoard[1] = CurrentBoard[1].clone();
NewBoard[2] = CurrentBoard[1].clone();
memory = NewBoard[ZeroPositionX][ZeroPositionY - 1];
NewBoard[ZeroPositionY- 1][ZeroPositionX] = 0;
NewBoard[ZeroPositionY][ZeroPositionX] = memory;
}
注意,我们必须调用clone
三次,因为它无法完全克隆双暗阵列(请参阅here)。
更简洁的方法是创建一个这样的Board
类(未经测试,请原谅错别字):
public class Board {
private int[][] content = new int[3][3];
/**
* Creates a new empty board.
*/
public Board() {
}
/**
* Call this constructor to create a new instance of a given board.
*/
public Board(Board otherBoard) {
this.content[0] = otherBoard.content[0].clone()
this.content[1] = otherBoard.content[1].clone()
this.content[2] = otherBoard.content[2].clone()
}
public void set(int a, int b, int value) {
content[a][b] = value;
}
public int get(int a, int b) {
return content[a][b];
}
public int hashCode() {
int code = 0;
for (int a=0; a<3; a++) {
for (int b=0; b<3; b++) {
code += content[a][b];
}
}
return code;
}
public boolean equals(Object that) {
if (!(that instanceof Board)) return false;
return Arrays.equals(this.content[0], that.content[0])
&& Arrays.equals(this.content[1], that.content[1])
&& Arrays.equals(this.content[2], that.content[2])
}
}
总的来说,您应该在https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
中研究Map
的一般合同
此外,在您的代码中,确保在<{1}}中使用密钥后,永远不会更改密钥的内容。否则混乱就会统治......
祝你好运。