我正在尝试制作一个哈希图以将权重添加到特定项目。但是,一旦我开始向其中添加更多项目,它也会更新现有项目。

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值的引用。

java - Java哈希图在放置新条目时会编辑现有条目-LMLPHP
这只是Alt + F8,并且在第3次调用addBlock()之后评估地图。我一直在#put上保持调试点。
java - Java哈希图在放置新条目时会编辑现有条目-LMLPHP
当我第二次在仍然保持同一行的状态下按评估键时,您会看到对Double change的引用。

如果我在规范化和非规范化中注释掉代码,它将始终为我提供相同的引用。

因此,您必须清楚在这些功能中将要发生的事情,也许我可以帮忙。从这一点来看,它看起来像是更新,您的一些评论指出您想要添加新项目,而这是您编写它所无法实现的。

因为我对您想要的内容并不确定100%,所以我需要更多详细信息,而且我可能做得不好,但是请随时对此发表评论。

07-24 13:36