Java hashmap在放入新条目时编辑现有条目

时间:2018-05-09 11:30:35

标签: java hashmap

我正在尝试创建一个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

2 个答案:

答案 0 :(得分:1)

当您注释掉标准化和非常化部分时,它会在拨打电话后更新任何内容。你搞砸了那些方法中的引用,所以如果你把一个调试点放在weightedBlocks.put(new PathMaterial(mat,data),weight)上;并且连续几次评估encryptedBlocks,你会发现每次评估时都会改变对double值的引用。

First Call 这只是Alt + F8并在第三次调用addBlock()后评估map。我一直在#put上保持调试点。 Second Call 我第二次按下评估,同时仍然保持在同一行,你可以看到对Double change的引用。

如果我在normalize和denormalize中注释掉代码,它会给我总是相同的引用。

所以你必须清楚你要做的事情才能发生,也许我可以提供帮助。从这一点来看,它看起来像更新,你的一些评论指出你想要添加新项目,这是你写的不可能的。

因为我不清楚100%关于你想要什么,我需要更多细节,我可能没有做对,但请随时对此发表评论。

答案 1 :(得分:0)

您的代码将更新现有项目,因为在更新项目时您无法限制代码。 (或)无处重新初始化变量。