2017-01-09 89 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);