使用LinkedHashMap.containsKey()会得到奇怪的结果

时间:2017-01-09 17:06:20

标签: java

我对Java编程有点新意,但我目前正在为一些生产过程开发模拟器。在这样做的过程中,我发现了一些非常奇怪的东西,我似乎无法弄清楚,也无法在互联网或其他任何问题上找到。

作为生产工厂的一部分,我需要一个特定的组件来确定它是否可以根据物品的配方将物品发送到任何机器。为此,我发现使用LinkedHashMap是解决此类问题的一个很好的实现。下一段代码描述了机器的设置并创建了初始的HashMap。它使用一组机器配置,每个配置都有一个与它们兼容的配方列表。 HashMap的格式为<Recipe, List<Machine>>,以便我可以通过搜索到达的项目的配方来查找可用的计算机。

public void setupMachines(List<Config> configurationList) {
    for (int i = 0; i<configurationList.size(); i++) {
        Config config = configurationList.get(i);
        Machine machine = new Machine(config, config.getName());

        for (int j = 0; j<config.getCompatibleRecipes().size(); j++){
            Recipe key = config.getCompatibleRecipes().get(j);
            if (!recipeInfo.containsKey(key)) {
                recipeInfo.put(key, new ArrayList<Machine>());
            }
            recipeInfo.get(key).add();
        }
    }
}

在机器组的类中,以下代码用于根据从模拟器获得的配方为项找到合适的机器,并将该项从队列发送到该机器。

public void checkAvailableMachinesAndRedirectItems() {
    int i = 0;
    while (i<queue.size()) {
        Lot lot = queue.get(i);
        Recipe key = lot.getRecipe();

        if (recipeInfo.containsKey(key)) { 
            if (!recipeInfo.get(key).isEmpty()) {
                Machine machine = recipeInfo.get(key).get(0);
                lot.setReservedMachine(machine);
                removeFromRecipeInfo(machine);
                queue.remove(lot);
                machine.take(lot);
            }
            else { i++; }
        }
        else { i++; }
    }
}

在模拟器的测试文件中,我必须遵循一段代码来构建两个简单的配方和运行模拟所需的一组机器。

MachineGroup machineGroup = new MachineGroup();
ArrayList<Config> configurationList = new ArrayList<Config>();    

//create two recipes:
Recipe recipeA = model.getSimFactory().createRecipe("RecipeA");
Recipe recipeB = model.getSimFactory().createRecipe("RecipeB");

//both recipes need to have the process step of passing through a machine
recipeA.add( new ProcessStep("MachineStep", machineGroup, ...with a bunch of variables... ) );
recipeB.add( new ProcessStep("MachineStep", machineGroup, ...with a bunch of variables... ) );

//Create two machine configurations:
Config configA = new Config(...bunch of variables...);
Config configB = new Config(...bunch of variables...);

//For this example both configs have just one compatible recipe:
configA.addCompatibleRecipe(recipeA);
configB.addCompatibleRecipe(recipeB);

//add both configs tho a list:
configurationList.add(configA);
configurationList.add(configB);

// -- THIS IS THE IMPORTANT STATEMENT -- \\
machineGroup.setupMachines(configurationList);
// *** ------- **** \\

//create a sink for deleted items that are completed:
model.getSimFactory().createProcessStepAndAddToRecipe("sinkStep", sink, recipeA);
model.getSimFactory().createProcessStepAndAddToRecipe("sinkStep", sink, recipeB);

//create a source for items with different recipes and inter arrival times:
Source sourceA = model.getSimFactory().createSource("SourceA", recipeA, 10L);
Source sourceB = model.getSimFactory().createSource("SourceB", recipeB, 8L);

engine.init(model);
model.addComponent(machineGroup);
engine.runSimulation(50L);

初始化模拟(这些东西已经正常工作)并使用machineGroup.setupMachines()函数创建具有初始HashMap的工厂设置,如下所示:{RecipeA=[MachineConfigA], RecipeB=[MachineConfigB]}。但是,第二段代码中的第一个IF语句(询问recipeInfo是否包含属于该批次的配方)从不返回true,甚至认为HashCodes为该批次的配方和配方目前在HashMap中充当关键值的是相同的。

现在由于某种原因我自己也不知道我在machineGroup.setupMachines()函数上面的engine.runSimulation()函数尝试了这个,奇怪的是IF语句现在似乎工作正常。我首先想到这与在构建初始HashMap(源和接收器)之后向配方添加一些步骤有关,但是从浏览互联网我得出的结论是,我甚至认为对象本身可能已经改变,关键值在HashMap中只有一个仍然指向Object的指针对吗?他们又有相同的HashCodes。

我的上司也无法弄清楚这种行为,但由于他使用LinkedHashMap很多,他和我真的想要更多关于这个主题的信息。有谁知道这里发生了什么?

我想再说一遍,我还不是一个javaguru,所以你的答案中的简化和例子非常受欢迎:)。

1 个答案:

答案 0 :(得分:0)

通常,此问题与您存储在HashMap的Key中的对象有关。该类不会覆盖hashCode()或/并且不会覆盖equals()

您应该验证存储和测试的对象是否相等。

内部比较代码可以帮助您理解原因。 (HashMap.getNode())的简化Java源代码

            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);