Cannot delete or find object in Java CopyOnWriteArraySet

I use CopyOnWriteArraySet to store one instance of a custom class that looks like this:

public class MyClass{ String _name; public MyClass(String name){ _name = name; } @Override public int hashCode(){ return _name.hashCode(); } @Override public boolean equals(Object obj){ if (obj == this) return true; if ((obj instanceof MyClass) == false) return false; MyClass otherObject = (MyClass) obj; return _name.equals(otherObject._name); } @Override public String toString(){ return _name; } } 

When I print a set, everything looks fine:

 MyClass theObject = new MyClass("Object 1"); CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet(); theSet.add(theObject); for (MyClass tmp : theSet){ System.out.println(tmp.toString()); } 

Result:

Object 1

So, obviously, the object is in the set.

Now I want to remove an object from the set:

 theSet.remove(theObject); 

Then I print the contents of the set again. Result:

Object 1

Very strange. So, I tried this:

 System.out.println(String.valueOf(theSet.contains(theObject))); 

Result:

falsely

Obviously, the collection cannot find theObject , although it is. So, I thought something was wrong with the equals() method. Thus, I changed the overrides of the equals() and hashCode() method, adding console printing to the first line of each function:

  @Override public int hashCode(){ System.out.println("hashCode() called"); return _name.hashCode(); } @Override public boolean equals(Object obj){ System.out.println("equals() called"); if (obj == this) return true; if ((obj instanceof MyClass) == false) return false; MyClass otherObject = (MyClass) obj; return _name.equals(otherObject.name); } 

Then again I call:

 theSet.remove(theObject); 

Result:

hashCode () is called

So, is the equals() method not called at all?

Can someone explain what is going on there?

I already tried to compare the hash codes of theObject and the instance inside the set, and they are both equal.

+6
source share
3 answers

I found the cause of the problem.

I use Hibernate, which creates my own instance of org.hibernate.collection.PersistentSet, which replaced my CopyOnWriteArraySet instance!

The fact that .contains () and .remove () didn't work was a bug in Hibernate: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3799

The solution in my case was to not override the .hashCode () method.

Note. This may not be the best solution for all cases. It worked for me. The link above describes several workarounds.

0
source

Strange ... and checked your codes. And it works well in my environment. And the remove operation does not call hashCode (), but instead calls equals (). In jdk, I used 1.6.0_23.

+1
source

A HashSet uses hashCode, however CopyOnWriteArraySet is not a HashSet (nor is it a TreeSet) and does not call hashCode (). If hashCode is called, you are not using this collection.


This is very strange because I cannot reproduce your problem.

 MyClass theObject = new MyClass("Object 1"); CopyOnWriteArrayList<MyClass> theSet = new CopyOnWriteArrayList(); // OR CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet(); theSet.add(theObject); System.out.println("After add."); System.out.println(theSet); theSet.remove(theObject); System.out.println("\nAfter remove"); System.out.println(theSet); 

prints

 After add. [Object 1] After remove [] 

Even when I change hashCode to

 public int hashCode() { throw new UnsupportedOperationException(); } 

it gets the same result because these classes do not use hashCode () (except for the hashCode () method)

0
source

Source: https://habr.com/ru/post/890062/


All Articles