Java:从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集合是不安全的?有人告诉我,不应该在

考虑给定的代码段。这个对象在引入m_nTurnPlaced成员之前是不可变的(可以通过setturnplace方法进行修改,所以现在GamePiece变得可变)

GamePiece用于ArrayList,我调用contains和remove方法,这两种方法都依赖于要实现的equals方法


我的问题是,在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()
上考虑它

这是什么意思

  • 首先,
    GamePiece
    的hashcode在您更改
    m\u nTurnPlaced
    时不会更改,这很好!否则就不能使用hashmaps或HashSet
  • 当您使用添加或删除列表时,您将正确考虑
    游戏状态
    :这实际上意味着您无法用不同的
    m\n放置的
    值区分两个
    游戏状态

    • 平等具有你想要赋予它的含义

      在您的案例中,您明确表示具有不同
      m\u nTurnPlaced
      GamePiece
      实例将被视为平等对象。因此,
      m\u nTurnPlaced
      是这个对象的一个状态,不应该在
      equals(o)
      hashcode()
      上考虑它

      这是什么意思

      • 首先,
        GamePiece
        的hashcode在您更改
        m\u nTurnPlaced
        时不会更改,这很好!否则就不能使用hashmaps或HashSet
      • 当您使用添加或删除列表时,您将正确考虑
        游戏状态
        :这实际上意味着您无法用不同的
        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有意义,那么就这样做。

      注意:这个答案是正确的