2017-01-09 83 views
0

我对Java编程有点新,但我目前正在为一些生产过程开发模拟器。在这样做的过程中,我发现了一些非常奇怪的东西,我似乎无法找到,也无法在互联网上或其他任何问题上找到。使用LinkedHashMap.containsKey()给出了奇怪的结果

作为生产工厂的一部分,我需要某个组件来确定它是否可以根据物料的配方将物料发送到其任何机器。为此,我发现使用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中只有一个指针仍然指向对象的权利?他们再次拥有相同的HashCodes。

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

我想重申一下,我不是一个javaguru呢,所以在你的答案中的简化和例子非常感谢:)。

+7

如果你看到有HashMap的键不可靠的问题,我的第一个猜测是,Recipe.hashCode()方法是基于可变状态计算其返回的值。将关键对象的hashCode添加到HashMap后更改它将破坏HashMap的功能。编辑你的问题,并包括食谱类的代码,以获得更确切的答案。 – VGR

回答

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);