groovyready-api

How to Use Groovy to find the INTERSECTION of two lists?


I am trying to retrieve the common items across two lists using Groovy. The following code works just fine, i.e the output from running this code is "DEBUG found in common Items : same". So far so good!

def list1 = ["same", "different"]
def list2 = ["same", "not the same"] 

def commonItems = list1.intersect(list2)

for(int i=0; i < commonItems.size(); i++)
{
    log.info("DEBUG found in common Items : " + commonItems[i])
}

I hit an issue when I try to apply the above principle to a list of objects - my issue is that the 'commonItems' list does NOT contain the single object I would expect, but is empty. Please note, my custom object 'ErrorWarningDetail' does override compareTo. Can someone see what I am doing wrong / make any suggestions? Thanks in advance!

First of all here is my custom class - note 'CompateTo' just checks the 'Code' field for now.

class ErrorWarningDetail implements Comparable
{
    public String Code
    public String Description
    public String ErrorType
    public String State  

    @Override
    int compareTo(Object o) {
        int result = Code <=> o.Code
        result
    }
}

Now here is the code that does the business. I would expect one object to be in 'commonItems' but it is infact empty - what am i doing wrong here? The output of running this is "DEBUG no common items"

def similarONE = new ErrorWarningDetail()
similarONE.Code = "100-1"
def similarTWO =new ErrorWarningDetail()
similarTWO.Code = "100-1"
def completelyDifferent = new ErrorWarningDetail()
completelyDifferent.Code = "697-2"

def List1 = []
def List2 = []
List1.add(similarONE)
List1.add(completelyDifferent)
List2.add(similarTwo)

def commonItems = list1.intersect(list2)

if (commonItems.size() == 0)
{
    log.info("DEBUG no common items")   
}



Solution

  • Implementing compareTo() is not enough in Java, you should be implementing equals/hashCode instead.

    In Groovy there's a handy annotation for that. So, the script down below executes successfully:

    import groovy.transform.EqualsAndHashCode
      
    @EqualsAndHashCode( includes = [ 'code' ] )
    class ErrorWarningDetail implements Comparable {
          String code
          String description
          String errorType
          String state
      
          @Override
          int compareTo(Object o) {
              code <=> ( o?.code ?: '' )
          }
    }
      
    def similarONE = new ErrorWarningDetail( code:"100-1" )
    def similarTWO = new ErrorWarningDetail( code:"100-1" )
    def completelyDifferent = new ErrorWarningDetail( code:"697-2" )
    
    def list1 = [similarONE, completelyDifferent]
    def list2 = [similarTWO]
    
    def commonItems = list1.intersect list2
    
    assert 1 == commonItems.size()
    

    P.S. Please, DO NOT name fields starting with Capital letters!