Java:从equals方法中省略数据成员
考虑给定的代码段。这个对象在引入m_nTurnPlaced成员之前是不可变的(可以通过setturnplace方法进行修改,所以现在GamePiece变得可变) GamePiece用于ArrayList,我调用contains和remove方法,这两种方法都依赖于要实现的equals方法Java:从equals方法中省略数据成员,java,collections,arraylist,equals,immutability,Java,Collections,Arraylist,Equals,Immutability,考虑给定的代码段。这个对象在引入m_nTurnPlaced成员之前是不可变的(可以通过setturnplace方法进行修改,所以现在GamePiece变得可变) GamePiece用于ArrayList,我调用contains和remove方法,这两种方法都依赖于要实现的equals方法 我的问题是,在Java中,一些成员不影响equals和hashcode可以吗?这将如何影响它在我的ArrayList中的使用?既然这个对象是可变的,那么使用哪种类型的java集合是不安全的?有人告诉我,不应该在
我的问题是,在Java中,一些成员不影响equals和hashcode可以吗?这将如何影响它在我的ArrayList中的使用?既然这个对象是可变的,那么使用哪种类型的java集合是不安全的?有人告诉我,不应该在可变对象上重写equals,因为它会导致某些集合的行为“异常”(我在java文档中的某个地方读到了这一点)。部分好处在于,您可以根据对象的需要自由设计
.equals()
和.hashcode()
某些类型的集合非常依赖于
.equals()
和.hashcode()
的一致性 部分好处在于,您可以根据对象的需要自由设计.equals()
和.hashcode()
某些类型的集合非常依赖于
.equals()
和.hashcode()
的一致性 平等具有你想要赋予它的含义
在您的案例中,您明确表示具有不同m\u nTurnPlaced
的GamePiece
实例将被视为平等对象。因此,m\u nTurnPlaced
是这个对象的一个状态,不应该在equals(o)
和hashcode()
上考虑它
这是什么意思
- 首先,
的hashcode在您更改GamePiece
时不会更改,这很好!否则就不能使用hashmaps或HashSetm\u nTurnPlaced
- 当您使用添加或删除列表时,您将正确考虑
:这实际上意味着您无法用不同的游戏状态
m\n放置的
值区分两个
游戏状态
- 平等具有你想要赋予它的含义
在您的案例中,您明确表示具有不同
m\u nTurnPlaced
的GamePiece
实例将被视为平等对象。因此,m\u nTurnPlaced
是这个对象的一个状态,不应该在equals(o)
和hashcode()
上考虑它
这是什么意思
- 首先,
的hashcode在您更改GamePiece
时不会更改,这很好!否则就不能使用hashmaps或HashSetm\u nTurnPlaced
- 当您使用添加或删除列表时,您将正确考虑
:这实际上意味着您无法用不同的游戏状态
m\n放置的
值区分两个
游戏状态
等于和hashCode
,以及你如何/当你改变对象时,会导致集合行为“异常”。下面是一个例子:
public class GamePiece {
public GamePiece(char cLetter, int nPointValue) {
m_cLetter=cLetter;
m_nPointValue=nPointValue;
m_nTurnPlaced=0; //has not been placed on game board yet.
}
public char GetLetter() {return m_cLetter;}
public int GetPointValue() {return m_nPointValue;}
public int GetTurnPlaced() {return m_nTurnPlaced;}
public void SetTurnPlaced(int nTurnPlaced) { m_nTurnPlaced=nTurnPlaced; }
@Override
public boolean equals(Object obj) {
/*NOTE to keep this shorter I omitted some of the null checking and instanceof stuff. */
GamePiece other = (GamePiece) obj;
//not case sensitive, and I don`t think we want it to be here.
if(m_cLetter != other.m_cLetter) {
return false;
}
if(m_nPointValue != other.m_nPointValue) {
return false;
}
/* NOTICE! m_nPointValue purposely omitted. It does not affect hashcode or equals */
return true;
}
@Override public int hashCode() {
/* NOTICE! m_nPointValue purposely omitted. It should not affect hashcode or equals */
final int prime = 41;
return prime * (prime + m_nPointValue + m_cLetter);
}
private char m_cLetter;
private int m_nPointValue;
private int m_nTurnPlaced;//turn which the game piece was placed on the game board. Does not affect equals or has code!
}
BitSet BitSet=new BitSet();
集合bitsetcol=newhashset();
bitsetcol.add(位集);
System.out.println(bitsetcol.contains(bitset));//打印正确
比特集(42);
System.out.println(bitsetcol.contains(bitset));//打印错误!!!
这里发生的是位集
定义了等于
和哈希码
HashSet
使用hashCode
和equals
查找对象。通过修改位集
,它现在有一个不同的hashCode
,因此bitsetcol
无法再找到它
您会注意到,如果bitsetcol=newarraylist()代码>,然后它仍然可以找到它!不同的集合
实现对这种突变机制有不同的容忍度
至于你能不能在一个可变类型上重写equals,是的,那当然可以<代码>位集
当然可以做到这一点。最重要的是,这正是您从位集
中所期望的行为(出于性能原因,位集设计为可变的)
如果您的可变类重写equals
和hashCode
是有意义的,那么就这样做。是的,当然,您如何定义您的equals
和hashCode
,以及您如何/何时变异对象,都会导致集合的行为“异常”。下面是一个例子:
public class GamePiece {
public GamePiece(char cLetter, int nPointValue) {
m_cLetter=cLetter;
m_nPointValue=nPointValue;
m_nTurnPlaced=0; //has not been placed on game board yet.
}
public char GetLetter() {return m_cLetter;}
public int GetPointValue() {return m_nPointValue;}
public int GetTurnPlaced() {return m_nTurnPlaced;}
public void SetTurnPlaced(int nTurnPlaced) { m_nTurnPlaced=nTurnPlaced; }
@Override
public boolean equals(Object obj) {
/*NOTE to keep this shorter I omitted some of the null checking and instanceof stuff. */
GamePiece other = (GamePiece) obj;
//not case sensitive, and I don`t think we want it to be here.
if(m_cLetter != other.m_cLetter) {
return false;
}
if(m_nPointValue != other.m_nPointValue) {
return false;
}
/* NOTICE! m_nPointValue purposely omitted. It does not affect hashcode or equals */
return true;
}
@Override public int hashCode() {
/* NOTICE! m_nPointValue purposely omitted. It should not affect hashcode or equals */
final int prime = 41;
return prime * (prime + m_nPointValue + m_cLetter);
}
private char m_cLetter;
private int m_nPointValue;
private int m_nTurnPlaced;//turn which the game piece was placed on the game board. Does not affect equals or has code!
}
BitSet BitSet=new BitSet();
集合bitsetcol=newhashset();
bitsetcol.add(位集);
System.out.println(bitsetcol.contains(bitset));//打印正确
比特集(42);
System.out.println(bitsetcol.contains(bitset));//打印错误!!!
这里发生的是位集
定义了等于
和哈希码
HashSet
使用hashCode
和equals
查找对象。通过修改位集
,它现在有一个不同的hashCode
,因此bitsetcol
无法再找到它
您会注意到,如果bitsetcol=newarraylist()代码>,然后它仍然可以找到它!不同的集合
实现对这种突变机制有不同的容忍度
至于你能不能在一个可变类型上重写equals,是的,那当然可以<代码>位集
当然可以做到这一点。最重要的是,这正是您从位集
中所期望的行为(出于性能原因,位集设计为可变的)
如果您的可变类重写equals和hashCode有意义,那么就这样做。注意:这个答案是正确的