2017-01-09 18 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++; } 
    } 
} 

2つの簡単なレシピやシミュレーションを実行するために必要なマシンのグループを構築するためにコードの一部を次のように。 {RecipeA=[MachineConfigA], RecipeB=[MachineConfigB]}:(このようなものはすでに正常に働いていた)、このようなものを探すのに初期のHashMapと工場出荷時の設定を作成するにはmachineGroup.setupMachines()機能を用いたシミュレーションを初期化し

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

。しかし、2番目のコードの最初のIF文(recipeInfoにロットに属するレシピが含まれているかどうか尋ねる)neverは、ロットのレシピと現在動作しているレシピのHashCodeであってもtrueを返しますHashMapのキー値は同一です。

今私は自分自身には知られていない何かの理由で、engine.runSimulation()関数のすぐ上にあるmachineGroup.setupMachines()関数でこれを試しましたが、奇妙なことはIF文がうまくいくように見えることです。私は最初にこれが最初のHashMap(ソースとシンク)を構築した後にレシピにいくつかのステップを追加することと関係があると考えましたが、インターネットを閲覧することから、オブジェクト自体が変更された可能性があると主張しました。 HashMapでは、まだオブジェクトの権利を指しているポインタだけですか?ここでも同じHashCodeがあります。

私の上司もこの動作を理解できませんでしたが、彼はLinkedHashMapを多く使用していたため、このトピックに関するいくつかの情報が本当に好きです。誰がここで何が起こっているのか知っていますか?

私はまだjavaguruではないので、私はそれを繰り返すことを望みます、あなたの答えの簡素化と例は非常に感謝しています:)。

+7

あなたはHashMapのキーと信頼性のない行動を見ている場合は、私の最初の推測がRecipe.hashCode()メソッドが変更可能な状態に基づいて、その戻り値を計算していることです。キーオブジェクトのhashCodeをHashMapに追加した後に変更すると、HashMapの機能が破損します。あなたの質問を編集し、より決定的な答えのためにレシピクラスのコードを含めてください。 – VGR

答えて

0

通常、この問題は、HashMapのキーに格納するオブジェクトに関連しています。クラスが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); 
関連する問題