2013-09-21 64 views
1

我想要的數據,如果該鍵不已經在地圖上存在添加到我的HashMap中。出於某種原因,即使密鑰確實存在,hashmap也會添加它。我不知道爲什麼會發生這種情況。我的addEntity方法是問題。我正在試圖檢測密鑰已經在hashmap中,如果是,那麼什麼都不做。但是,無論密鑰是否已經存在,它都會因爲某種原因而始終添加密鑰。的HashMap <的String [],列表<int[]>>未檢測到重複的值

我的數據文件:

package timeTraveler.mechanics; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 
import java.util.Set; 

import net.minecraft.entity.EntityLiving; 

public class PathingData 
{ 
    /** 
    * Entity data array 
    */ 
    public static Map<String[], List<int[]>> allEntityData; 

    public PathingData() 
    { 
     allEntityData = new HashMap<String[], List<int[]>>(); 
    } 
    /** 
    * Adds an entity UUID (Unique ID)and MobType to the entity data ArrayList. If the entity already exists inside of the ArrayList, then it skips it. 
    * @param uuid 
    */ 
    public void addEntity(String[] entityData) 
    {  
     System.out.println(entityData[0]); 
     if(!allEntityData.containsKey(entityData)) 
     { 
      System.out.println("Adding entity!"); 
      allEntityData.put(entityData, new ArrayList<int[]>()); 
     } 
     else 
     { 
      System.out.println("ENTITY ALREADY EXISTS IN ARRAY"); 
     } 
    } 
    /** 
    * Adds data (X, Y, and Z) to the corresponding UUID (Unique ID) for the entity. If the entity's UUID does not exist, then it prints out a line that says the UUID cannot be found. 
    * @param uuid 
    * @param data 
    */ 
    public void addData(String[] entityData, String data) 
    { 
     System.out.println(entityData[0]); 
     if(allEntityData.containsKey(entityData)) 
     { 
      System.out.println("Adding data to entity!"); 
      int[] rawData = new int[3]; 
      String[] pureData = data.split(","); 

      rawData[0] = Integer.parseInt(pureData[0]); 
      rawData[1] = Integer.parseInt(pureData[1]); 
      rawData[2] = Integer.parseInt(pureData[2]); 

      List<int[]> entityLocData = allEntityData.get(entityData); 
      entityLocData.add(rawData); 
      allEntityData.put(entityData, entityLocData); 
     } 
     else 
     { 
      System.out.println("ENTITY DOES NOT EXIST IN ARRAY! :("); 
      //addEntity(entityData); 
     } 
    } 
    /** 
    * Gets the data for a specific UUID (Unique ID) for an entity. 
    * @param uuid 
    * @return 
    */ 
    public List<int[]> getDataForUUID(String[] entityData) 
    { 
     List<int[]> entityLoc = allEntityData.get(entityData); 
     return entityLoc; 
    } 
    /** 
    * Clears all entities and their corresponding data from the map. 
    */ 
    public void clearAllEntitiesAndData() 
    { 
     allEntityData.clear(); 
    } 

    /** 
    * Checks if entity exists inside of array 
    * @param uuid 
    * @return 
    */ 
    public boolean doesEntityExist(String[] entityData) 
    { 
     List<int[]> entityLoc = allEntityData.get(entityData); 
     if(entityData != null) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

我已經確信,只有一個變量的情況下,我總是指的是一個變量在我.addEntity和.addData。有任何想法嗎?

編輯:剛纔我已經試過落實提出了建議。但是,它仍然只是用[email protected]而不是數組打印出相同的東西。下面是修改後的代碼:

package timeTraveler.mechanics; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 
import java.util.Set; 

import timeTraveler.core.StringArrayHolder; 

import net.minecraft.entity.EntityLiving; 

public class PathingData 
{ 
    /** 
    * Entity data array 
    */ 
    public static Map<StringArrayHolder, List<int[]>> allEntityData; 

    public PathingData() 
    { 
     allEntityData = new HashMap<StringArrayHolder, List<int[]>>(); 
    } 
    /** 
    * Adds an entity UUID (Unique ID)and MobType to the entity data ArrayList. If the entity already exists inside of the ArrayList, then it skips it. 
    * @param uuid 
    */ 
    public void addEntity(StringArrayHolder entityData) 
    {  
     System.out.println(entityData); 
     if(!allEntityData.containsKey(entityData)) 
     { 
      System.out.println("Adding entity!"); 
      allEntityData.put(entityData, new ArrayList<int[]>()); 
     } 
     else 
     { 
      System.out.println("ENTITY ALREADY EXISTS IN ARRAY"); 
     } 
    } 
    /** 
    * Adds data (X, Y, and Z) to the corresponding UUID (Unique ID) for the entity. If the entity's UUID does not exist, then it prints out a line that says the UUID cannot be found. 
    * @param uuid 
    * @param data 
    */ 
    public void addData(StringArrayHolder entityData, String data) 
    { 
     System.out.println(entityData); 
     if(allEntityData.containsKey(entityData)) 
     { 
      System.out.println("Adding data to entity!"); 
      int[] rawData = new int[3]; 
      String[] pureData = data.split(","); 

      rawData[0] = Integer.parseInt(pureData[0]); 
      rawData[1] = Integer.parseInt(pureData[1]); 
      rawData[2] = Integer.parseInt(pureData[2]); 

      List<int[]> entityLocData = allEntityData.get(entityData); 
      entityLocData.add(rawData); 
      allEntityData.put(entityData, entityLocData); 
     } 
     else 
     { 
      System.out.println("ENTITY DOES NOT EXIST IN ARRAY! :("); 
      //addEntity(entityData); 
     } 
    } 
    /** 
    * Gets the data for a specific UUID (Unique ID) for an entity. 
    * @param uuid 
    * @return 
    */ 
    public List<int[]> getDataForUUID(StringArrayHolder entityData) 
    { 
     List<int[]> entityLoc = allEntityData.get(entityData); 
     return entityLoc; 
    } 
    /** 
    * Clears all entities and their corresponding data from the map. 
    */ 
    public void clearAllEntitiesAndData() 
    { 
     allEntityData.clear(); 
    } 

    /** 
    * Checks if entity exists inside of array 
    * @param uuid 
    * @return 
    */ 
    public boolean doesEntityExist(StringArrayHolder entityData) 
    { 
     List<int[]> entityLoc = allEntityData.get(entityData); 
     if(entityData != null) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

和包裝:

package timeTraveler.core; 

import java.util.ArrayList; 

public class StringArrayHolder 
{ 
    private String[] data; 

    public StringArrayHolder() 
    { 
     data = new String[2]; 
    } 

    public void setData(String[] data) 
    { 
     this.data = data; 
    } 
    public String[] getData() 
    { 
     return this.data; 
    } 

    @Override 
    public int hashCode() 
    { 
     return 0; 
     //... 
    } 

    @Override 
    public boolean equals(Object o) 
    { 
     if(data.equals(o)) 
     { 
      return true; 
     } 
     return false; 
     //... 
    } 

} 
+0

的可能重複的[可Java數組被用作一個HashMap鍵](http://stackoverflow.com/questions/16839182/can-a-java-array-be-used-as-a-hashmap-key ) – Raedwald

回答

13

的問題是,陣列不從Object類中重寫equals也不hashCode方法,這樣即使你添加一個新的String[]與相同的值,它將是你的地圖中的一個不同的鍵。

一個可能的解決方案是創建一個包裝類,它將爲您保留String[]並覆蓋其中的equalshashCode方法。

public class MyStringArrayHolder { 

    private String[] data; 

    //class constructor... 

    //getters and setters for the array... 

    @Override 
    public int hashCode() { 
     //... 
    } 

    @Override 
    public boolean equals(Object o) { 
     //... 
    } 
} 

對於equalshashCode方法的實現,你可以在這個包裝類使用Arrays#equalsArrays#hashCode


從您的評論:

我addEntity方法的問題。我正在試圖檢測密鑰已經在hashmap中,如果是,那麼什麼都不做。但是,無論密鑰是否已經存在,它都會因爲某種原因而始終添加密鑰。

這就是我上面解釋過的。該方法Map#containsKey明確指出這一點:

回報true當且僅當此映射包含的映射關係的關鍵k這樣(key==null ? k==null : key.equals(k))

因爲數組覆蓋Object#equals,你不會即使它們在相同位置具有相同的元素,也有兩個類似的數組鍵。


編輯:根據您當前編輯的問題在equalshashCode方法實現。我已經完成了MyStringArrayHolder類的基本實現,並複製/粘貼了PathingData類的代碼。這按預期工作(至少在這個情況下):

class MyStringArrayHolder { 
    private final String[] data; 
    //I do not want any client could change the array reference 
    //this also explains why this field doesn't have a setter 
    public MyStringArrayHolder(String[] data) { 
     this.data = data; 
    } 
    public String[] getData() { 
     return this.data; 
    } 
    @Override 
    public int hashCode() { 
     return Arrays.hashCode(data); 
    } 
    @Override 
    public boolean equals(Object o) { 
     if (o == null) return false; 
     if (o == this) return true; 
     if (o instanceof MyStringArrayHolder) { 
      MyStringArrayHolder other = (MyStringArrayHolder)o; 
      return Arrays.equals(this.data, other.data); 
     } 
     return false; 
    } 
    //just to print in console for testing purposes 
    @Override 
    public String toString() { 
     return Arrays.deepToString(data); 
    } 
} 

public class PathingData { 
    //removed the static modifier, not really sure why you need it like that 
    public Map<MyStringArrayHolder, List<int[]>> allEntityData; 
    //current class implementation... 
    //just to print in console for testing purposes 
    @Override 
public String toString() { 
    return allEntityData.toString(); 
} 
public static void main(String[] args) { 
    PathingData pathingData = new PathingData(); 
    String[] example1 = { "hello", "world" }; 
    String[] example2 = { "luiggi", "mendoza" }; 
    String[] example3 = { "hello", "world" }; 
    MyStringArrayHolder holder1 = new MyStringArrayHolder(example1); 
    MyStringArrayHolder holder2 = new MyStringArrayHolder(example2); 
    MyStringArrayHolder holder3 = new MyStringArrayHolder(example3); 
    pathingData.addEntity(holder1); 
    pathingData.addEntity(holder2); 
    pathingData.addEntity(holder3); 
    pathingData.addData(holder1, "1,2,3"); 
    pathingData.addData(holder2, "4,5,6"); 
    pathingData.addData(holder3, "7,8,9"); 
    System.out.println(pathingData); 
} 
} 

輸出:

Adding entity! 
Adding entity! 
ENTITY ALREADY EXISTS IN ARRAY 
Adding data to entity! 
Adding data to entity! 
Adding data to entity! 
{[luiggi, mendoza]=[[[email protected]], [hello, world]=[[[email protected], [[email protected]]} 

注:含[[email protected]的最後一行是int[]的哈希碼。我建議將List<int[]>更改爲List<List<Integer>>,但此實現超出了問題的範圍:)。

+0

我的addEntity方法是問題所在。我正在試圖檢測密鑰已經在hashmap中,如果是,那麼什麼都不做。但是,無論密鑰是否已經存在,它都會因爲某種原因而始終添加密鑰。對不起,如果我沒有在OP中說清楚。 – Charsmud

+1

@Charsmud這篇文章告訴你到底是什麼原因。 –

+1

爲什麼不使用'HashMap ,List >'?我相當確信ArrayList實現'hashCode()'和'equals()'。 – azz

相關問題