如果键不存在于映射中,我将尝试向我的 HashMap 中添加数据。出于某种原因,即使 key 确实存在,hashmap 仍然会添加它。我不知道为什么会这样。我的 addEntity 方法是问题所在。我正在尝试检测 key 是否已经在 HashMap 中,如果是,则什么也不做。但是,出于某种原因,它总是会添加 key ,无论 key 是否已经存在。
我的数据文件:
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 中引用该变量。有什么想法吗?
编辑:我刚刚尝试实现所提出的建议。然而,它仍然只是打印出同样的东西,使用 timetraveler.core.StringArrayHolder@0 而不是数组。这是修改后的代码:
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;
//...
}
}
最佳答案
问题是数组不会覆盖 equals
也不hashCode
来自 Object
的方法类,因此即使您添加一个新的 String[]
具有相同的值,它将是您 map 中的不同键。
一个可能的解决方案是创建一个包装类来保存 String[]
为你覆盖 equals
和 hashCode
那里的方法。
public class MyStringArrayHolder {
private String[] data;
//class constructor...
//getters and setters for the array...
@Override
public int hashCode() {
//...
}
@Override
public boolean equals(Object o) {
//...
}
}
对于 equals
的实现和 hashCode
方法,你可以使用 Arrays#equals
和 Arrays#hashCode
在这个包装类中。
来自您的评论:
My addEntity method is the problem. I am trying to detect of the key is already in the hashmap, and if it is, then do nothing. However, it for some reason will always add the key, no matter if the key already exists.
这就是我上面所解释的。方法 Map#containsKey
明确指出:
returns
true
if and only if this map contains a mapping for a keyk
such that(key==null ? k==null : key.equals(k))
因为数组不会覆盖Object#equals
,你不会有两个相似的数组键,即使它们在相同的位置有相同的元素。
编辑:根据您当前的编辑,问题在 equals
中和 hashCode
方法实现。我已经基本实现了 MyStringArrayHolder
类并复制/粘贴 PathingData
的代码类(class)。这按预期工作(至少对于这种情况):
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]=[[I@35087359], [hello, world]=[[I@5a7691c0, [I@1e5b02a6]}
注意:最后一行包含[I@35087359
是 int[]
的当前哈希码.我建议从 List<int[]>
更改至 List<List<Integer>>
, 但是这个实现超出了问题的范围:)。
关于java - HashMap<String[], List<int[]>> 未检测到重复值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18934974/