我正在尝试制作一个哈希图以将权重添加到特定项目。但是,一旦我开始向其中添加更多项目,它也会更新现有项目。
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:
权重为1的PathMaterial(DIRT,1)
权重为1的PathMaterial(STONE,1)
权重为1的PathMaterial(STONE,2)
但是添加第三个项目后,PathMaterial(DIRT,1)的权重为2
此项的权重通过addBlock方法中的HashMap#put调用进行了更改(我通过调试器进行了检查,权重恰好在put调用之前,而在put调用之后是错误的)
我还上传了该项目here
最佳答案
当您注释掉对部分进行归一化和反归一化后,在放置调用后将不会更新任何内容。您将这些方法中的引用弄乱了,因此,如果将调试点放在weightedBlocks.put(new PathMaterial(mat,data),weight)上;并连续两次评估weightedBlocks,您会发现每次评估时都会更改对double值的引用。
这只是Alt + F8,并且在第3次调用addBlock()之后评估地图。我一直在#put上保持调试点。
当我第二次在仍然保持同一行的状态下按评估键时,您会看到对Double change的引用。
如果我在规范化和非规范化中注释掉代码,它将始终为我提供相同的引用。
因此,您必须清楚在这些功能中将要发生的事情,也许我可以帮忙。从这一点来看,它看起来像是更新,您的一些评论指出您想要添加新项目,而这是您编写它所无法实现的。
因为我对您想要的内容并不确定100%,所以我需要更多详细信息,而且我可能做得不好,但是请随时对此发表评论。