Groovy Map>> data manipulation method optimization Am trying to update the Map&lt;String,List&lt;Map&lt;String,String&gt;&gt;&gt; invoices with the invoiceErrors as below

InvoiceError // is an entity with below attributes
{ String errorMessage,
  String invoiceNumber    
}
ErrorMessage                                          invoiceNumber   
-------------                                       -------------------     
File Error : The file is in an unsupported format   INV-Error_Test1
Line : 1 Invoice does not foot Reported             INV-Error_Test1
Line : 2 MATH ERROR                                 INV-Error_Test1
Line : 3 MATH ERROR                                 INV-Error_Test2
Line : 3 Invoice does not foot Reported             INV-Error_Test2


Am trying to achieve below map 
    If the error message doesnt have a line number it need to be appended at the top level as invLineItems.put('error',['INV-Error_Test1' :File Error : The file is in an unsupported format])
   Otherwise errormessage should be appended to the  matching INVOICE and linenumber as below

invLineItems = [INV-Error_Test1:[[LINE:1, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test1, INVOICE_TOTAL:22, error : `Line : 1 Invoice does not foot Reported`], 
                                [LINE:2, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test1, INVOICE_TOTAL:24, error : `Line : 2 MATH ERROR`],
                INV-Error_Test2:[[LINE:3, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test2, INVOICE_TOTAL:26, , error : `Line : 3 MATH ERROR | Line : 3 Invoice does not foot Reported`], 
                                [LINE:4, INVOICE_DATE:20150301, INVOICE_NUMBER:INV-Error_Test2, INVOICE_TOTAL:28,]],
                error : [[INV-Error_Test1:`File Error : The file is in an unsupported format`]]


I wrote the below method to achieve the above

def regex = "^Line\\s(?:(\\d+)\\s)?\\s*:\\s+(\\d+)?.+";
for (e in invLineItems ){
  def errors =  lipErrors.findAll{it.invoiceNumber==e.key} // finding the error messages with the invoice number
  errors.each{  // fetching the line numbre from error message and finding the matching record the invoice number and line number in invLineItems 
     int lineNumber
     if (it.errorMessage.matches(regex)) {
            Pattern p = Pattern.compile("\\d+");
            Matcher m = p.matcher(it.errorMessage);
            if (m.find()) {
                 lineNumber = Integer.parseInt(m.group());
            }
          println "lineNumber = "+lineNumber
        }

    if(e.value['LINE_ITEM_NUMBER'].find{it==lineNumber.toString()}) {
      def data = lipErrors.findAll{it.invoiceNumber==e.key &amp;&amp; it.errorMessage.matches("^Line\\s+"+lineNumber+"?\\:\\s+"+lineNumber+"?.+")}
      e.getValue().each{it.put("error", data.errorMessage.join("|"))}

     }   

  }
}   


The code doesnt look like Groovy and using traditional java code mostly, am wondering whether the code can be simplified with Groovy approach
You can use Groovy's regular expression operators to create Java Matchers.

def invoices = [
'LEDES98BI V2',
'LINE|INVOICE_DATE|INVOICE_NUMBER|INVOICE_TOTAL',
'1|20150301|INV-Error_Test1|22',
'2|20150301|INV-Error_Test1|24',
'3|20150301|INV-Error_Test2|26',
'4|20150301|INV-Error_Test2|28,',
'5|20150301|INV WITH WHITESPACE|29,']    

def lines = invoices
    .findAll { it.contains('|') }
    .collect { it.tokenize('|') }

def headers = lines.first()
def invoiceMap =  lines.tail().collect{
    [headers, it].transpose().collectEntries()
}.groupBy{ it.INVOICE_NUMBER }

class InvoiceError {
    String errorMessage
    String invoiceNumber
}

[
    ['INV-Error_Test1', 'File Error : The file is in an unsupported format'],
    ['INV-Error_Test1', 'Line : 1 Invoice does not foot Reported'],
    ['INV-Error_Test1', 'Line : 2 MATH ERROR'],
    ['INV-Error_Test2', 'Line : 3 MATH ERROR'],
    ['INV-Error_Test2', 'Line : 3 Invoice does not foot Reported']
].collect {
    [['invoiceNumber', 'errorMessage'], it].transpose().collectEntries()
}.collect { it as InvoiceError }
.each {error -&gt;
   def matcher = error.errorMessage =~ /Line : (\d+) (.*)/

   if(matcher) {
       def lineNumber = matcher.group(1)
       def errorDescription = matcher.group(2)
       def line = invoiceMap[error.invoiceNumber]
           .find() { it.LINE == lineNumber }

       if(line.errors) {
           line.errors = "$line.errors |  $errorDescription"
       } else {
           line.errors = errorDescription
       }
   } else {
       if(!invoiceMap.errors) invoiceMap.errors = []
       invoiceMap.errors &lt;&lt; [(error.invoiceNumber): error.errorMessage]
   }
}

invoiceMap


In this example, I build the InvoiceError instances from a list that's transposed (btw, thank you for that trick). Each resulting map is coerced into an instance of InvoiceError.

I took a different approach by iterating through the errors and inserting them into the invoiceMap, rather than iterating through the invoiceMap and looking up the errors.