我正在尝试创建一个hashmap来为特定项添加权重。但是一旦我开始添加更多项目,它也会更新现有项目。
HashMap将PathMaterial映射到Double
这是我的PathMaterial类:
package com.test;
import java.text.DecimalFormat;
public class PathMaterial {
public enum Material {
AIR,
STONE,
GRASS,
DIRT;
int getId() {
return this.ordinal();
}
}
public Material mat;
public byte data;
public PathMaterial(Material mat, byte data) {
this.mat = mat;
this.data = data;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PathMaterial)) {
return false;
}
PathMaterial other = (PathMaterial) obj;
return mat == other.mat && data == other.data;
}
@Override
public int hashCode() {
return Integer.parseInt(
new DecimalFormat("000").format(mat.getId()) + "" + new DecimalFormat("00").format((int) data));
}
}
这是我用于权重和代码的代码:
package com.test;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
public class Main {
private HashMap<PathMaterial, Double> weightedBlocks;
int totalWeight;
public static void main(String[] args) {
new Main().run();
}
private void run() {
weightedBlocks = new HashMap<>();
totalWeight = 0;
addBlock(PathMaterial.Material.DIRT, 1, (byte)1);
addBlock(PathMaterial.Material.STONE, 1, (byte)1);
addBlock(PathMaterial.Material.STONE, 1, (byte)2);
System.out.println(toString());
}
private void denormalizeWeights() {
double previous = 0;
for (Map.Entry pair : weightedBlocks.entrySet()) {
weightedBlocks.put((PathMaterial) pair.getKey(),
(double) pair.getValue() - previous);
previous = (double) pair.getValue();
}
for (Map.Entry pair : weightedBlocks.entrySet()) {
weightedBlocks.put((PathMaterial) pair.getKey(),
(double) pair.getValue() * totalWeight);
}
}
private void normalizeWeights() {
for (Map.Entry pair : weightedBlocks.entrySet()) {
weightedBlocks.put((PathMaterial) pair.getKey(),
(double) pair.getValue() / totalWeight);
}
double previous = 0;
for (Map.Entry pair : weightedBlocks.entrySet()) {
weightedBlocks.put((PathMaterial) pair.getKey(),
(double) pair.getValue() + previous);
previous = (double) pair.getValue();
}
}
public void addBlock(final PathMaterial.Material mat, double weight, byte data) {
denormalizeWeights();
weightedBlocks.put(new PathMaterial(mat, data), weight);
// weightedBlocks.put(mat, weight);
totalWeight = getTotalWeight();
normalizeWeights();
}
private int getTotalWeight() {
int weight = 0;
for (double d : weightedBlocks.values()) {
weight += d;
}
return weight;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(
"PathBuilder with name '" + "test" + "'\nRadius: " + 3 + "\nWeightmap:");
denormalizeWeights();
for (Map.Entry pair : weightedBlocks.entrySet()) {
PathMaterial mat = (PathMaterial) pair.getKey();
String matName = mat.mat.name() + ":" + mat.data;
String percentage = new DecimalFormat("00.0").format(((double) pair.getValue()) / totalWeight * 100);
sb.append("\n-" + matName + " [" + percentage + "%]");
}
normalizeWeights();
return sb.toString();
}
}
在我的测试中,我按此顺序添加3个PathMaterials:
PathMaterial(DIRT,1),重量为1
PathMaterial(STONE,1),重量为1
PathMaterial(STONE,2),重量为1
但在添加第3项后,PathMaterial(DIRT,1)的权重为2
使用addBlock方法中的HashMap#put调用来更改此项的权重(我使用调试器检查,权重在put调用之前是正确的,并且在put调用之后是错误的)
我还上传了这个项目here
答案 0 :(得分:1)
当您注释掉标准化和非常化部分时,它会在拨打电话后更新任何内容。你搞砸了那些方法中的引用,所以如果你把一个调试点放在weightedBlocks.put(new PathMaterial(mat,data),weight)上;并且连续几次评估encryptedBlocks,你会发现每次评估时都会改变对double值的引用。
这只是Alt + F8并在第三次调用addBlock()后评估map。我一直在#put上保持调试点。 我第二次按下评估,同时仍然保持在同一行,你可以看到对Double change的引用。
如果我在normalize和denormalize中注释掉代码,它会给我总是相同的引用。
所以你必须清楚你要做的事情才能发生,也许我可以提供帮助。从这一点来看,它看起来像更新,你的一些评论指出你想要添加新项目,这是你写的不可能的。
因为我不清楚100%关于你想要什么,我需要更多细节,我可能没有做对,但请随时对此发表评论。
答案 1 :(得分:0)
您的代码将更新现有项目,因为在更新项目时您无法限制代码。 (或)无处重新初始化变量。