Java HashMap未检测到重复值
如果映射中不存在密钥,我将尝试向hashmap添加数据。出于某种原因,即使键确实存在,hashmap也会添加它。我不知道为什么会这样。我的加法就是这个问题。我试图检测hashmap中已经存在的密钥,如果存在,则什么也不做。但是,由于某种原因,它始终会添加密钥,无论该密钥是否已经存在 我的数据文件:Java HashMap未检测到重复值,java,hashmap,Java,Hashmap,如果映射中不存在密钥,我将尝试向hashmap添加数据。出于某种原因,即使键确实存在,hashmap也会添加它。我不知道为什么会这样。我的加法就是这个问题。我试图检测hashmap中已经存在的密钥,如果存在,则什么也不做。但是,由于某种原因,它始终会添加密钥,无论该密钥是否已经存在 我的数据文件: package timeTraveler.mechanics; import java.util.ArrayList; import java.util.Collection; import jav
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;
}
}
问题是数组不会覆盖对象类中的equals或hashCode方法,因此即使添加具有相同值的新字符串[],它在映射中也将是不同的键 一个可能的解决方案是创建一个包装器类,该类将为您保存字符串[],并覆盖那里的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方法的实现,您可以在此包装器类中使用and
根据您的评论:
我的加法就是这个问题。我试图检测hashmap中已经存在的密钥,如果存在,则什么也不做。但是,由于某种原因,它始终会添加密钥,无论该密钥是否已经存在
这就是我上面解释的。该方法明确规定:
当且仅当此映射包含键k的映射且键==null时,返回true?k==null:key.equalsk
由于数组不重写Objectequals,因此即使在同一位置有相同的元素,也不会有两个相似的数组键
编辑:根据您当前的编辑,问题在于equals和hashCode方法实现中。我已经完成了MyStringGarrayHolder类的基本实现,并复制/粘贴了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);
}
}
注意:最后一行包含[I@35087359是int[]的当前哈希代码。我建议从一个列表更改为另一个列表,但此实现超出了问题的范围:。问题是数组不重写对象类中的equals或hashCode方法,因此即使添加新字符串[]使用相同的值,它将是地图中的不同键 一个可能的解决方案是创建一个包装器类,该类将为您保存字符串[],并覆盖那里的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方法的实现,您可以在此包装器类中使用and
根据您的评论:
我的加法方法就是问题所在。我正在尝试检测hashmap中是否已经存在密钥,如果已经存在,则什么也不做。但是,出于某种原因,它将始终添加密钥,无论密钥是否已经存在
这就是我上面解释的。该方法清楚地说明了这一点:
当且仅当此映射包含键k的映射,使得key==null?k==null:key.equalsk时,返回true
由于数组不重写Objectequals,因此即使在同一位置有相同的元素,也不会有两个相似的数组键
编辑:根据您当前的编辑,问题出在equals和hashCode方法实现中。我对MyStringGarrayHolder类进行了基本实现,并复制/粘贴了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);
}
}
注意:最后一行包含[I@35087359是int[]的当前哈希代码。我建议从一个列表改为另一个列表,但这个实现超出了问题的范围:。@Charsmud,这篇文章告诉了你这到底是为什么。为什么不使用HashMapLuiggi,你应该提到JDK中为这个用例提供的Arrays.equals和Arrays.hashCode方法。不需要包装器,只要使用它就可以了数组。asList@LuiggiMendoza抱歉,刚才看到了您关于Arrays.asList的问题。它确实实现了equals和hashCode,是的。事实上,这两个函数的行为都是在List接口中指定的,所以List的所有正确实现都必须实现这些方法和指定的行为。@Charsmud和这篇文章告诉您确切的原因是。为什么不使用HashMapLuiggi呢?您应该提到JDK中为这个用例提供的Arrays.equals和Arrays.hashCode方法。不需要包装器,只需要使用数组。asList@LuiggiMendoza抱歉,刚才看到了您关于Arrays.asList的问题。它确实实现了equals和hashCode,是的。事实上,这两个函数的行为都是在列表接口中指定,因此列表的所有正确实现都必须实现这些方法和指定的行为。的可能重复
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]}