Trebla
Trebla

Reputation: 1172

List.retainAll() not working as expected (grails 2.3.9)

I'm almost certainly doing something wrong or misunderstanding List.retainAll().

I have two lists that are equal (size() ==1), yet when I call list1.retainAll(list2), list 1 becomes empty.

Code:

List<DomainObject> list1 = someService.getData()
List<DomainObject> list2 = someService.getOtherData()
log.info("Equal: ${list1.equals(list2)}") 
boolean changed = list1.retainAll(list2)
log.info("Changed: ${changed}")
log.info("list1 empty: ${list1.isEmpty()}")

Log shows:

Equal: true
Changed: true
list1 empty: true

I... don't know what I'm doing wrong. I've run tests with more generic objects (the actual domain object is fairly complex, but implements equals/hashcode correctly) and retainAll worked as expected.

I'm not even sure what specific question I should be asking... Are there conditions I'm missing where equals() can return true but retainAll() fails?

Upvotes: 0

Views: 527

Answers (1)

Trebla
Trebla

Reputation: 1172

Hopefully to help someone else down the line, and this is something I should have known and had run into before.

list1.equals(list2) //true, one element per list
list1.get(0).id == list2.get(0).id //true, same DB object
list1.get(0).equals(list2.get(0))  //false...  ?!

The reason was equals() was implemented starting with:

equals() {  
    if(getClass() != o.class) return false
}

getClass() was returning DomainObject but o.class (or o.getClass()) was returning javaassist__blahblah.

I replaced the check with

if(!(o instanceof DomainObject)) return false

Not sure if that's the cleanest way to do class checking in equals, for some reason I was of the impression that instanceof was slow.

Upvotes: 1

Related Questions