24

Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

  • Upload
    others

  • View
    9

  • Download
    2

Embed Size (px)

Citation preview

Page 1: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month
Page 2: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Groovy Goodness NotebookExperience the Groovy programming language through code snippets

Hubert A. Klein Ikkink (mrhaki)

This book is for sale at http://leanpub.com/groovy-goodness-notebook

This version was published on 2016-11-18

This is a Leanpub book. Leanpub empowers authors and publishers with the LeanPublishing process. Lean Publishing is the act of publishing an in-progress ebook usinglightweight tools and many iterations to get reader feedback, pivot until you have theright book and build traction once you do.

© 2012 - 2016 Hubert A. Klein Ikkink (mrhaki)

Page 3: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Tweet This Book!Please help Hubert A. Klein Ikkink (mrhaki) by spreading the word about this book onTwitter!

The suggested tweet for this book is:

I just bought Groovy Goodness Notebook with Groovy Goodness blog posts bundled intoone book. #groovy @mrhaki

The suggested hashtag for this book is #groovygoodnessnotebook.

Find out what other people are saying about the book by clicking on this link to searchfor this hashtag on Twitter:

https://twitter.com/search?q=#groovygoodnessnotebook

Page 4: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Also By Hubert A. Klein Ikkink (mrhaki)Grails Goodness Notebook

Gradle Goodness Notebook

Spocklight Notebook

Awesome Asciidoctor Notebook

Ratpacked Notebook

Page 5: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

This book is dedicated to my lovely family. I love you.

Page 6: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Contents

Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Working with Dates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Setting Date and Calendar Values with Subscript Operators . . . . . . . . . . . . . 2Convert Date to java.sql.Timestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Convert Date to Calendar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Format Dates with TimeZone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Parse Date.toString() Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Use the set Method to Define a Date or Calendar Value . . . . . . . . . . . . . . . . 4Create New Date from Old Date with Updates . . . . . . . . . . . . . . . . . . . . . 5Create New Date or Calendar from Existing and Set Property Value . . . . . . . . 5Clear Time Portion of a Date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6Date and Time Durations and the TimeCategory . . . . . . . . . . . . . . . . . . . . 6Loop Through Date and Calendar Ranges . . . . . . . . . . . . . . . . . . . . . . . . 7

Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Check if Maps are Equal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Sorting a Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Turn a List into a Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Complex Keys in Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Use inject Method on a Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Intersect Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Subtracting Map Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12Process Map Entries in Reverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13Getting a Submap from a Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13Grouping Map Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14Get Value from Map or a Default Value . . . . . . . . . . . . . . . . . . . . . . . . . . 15Map with Default Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15Determine Min and Max Entries in a Map . . . . . . . . . . . . . . . . . . . . . . . . 16Represent Map As String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Turn A Map Or List As String To Map Or List . . . . . . . . . . . . . . . . . . . . . . 17

Page 7: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates

Working with Dates

Thanks to Groovy’s extensions to the JDK Date classes we can work with dates more easily.For example we can now add and subtract days with the plus() and minus()methods. Andbecause this methods are mapped to the operators + and - we can write dense code.

Also the next() and previous() methods are implemented so we can use the ++ and --operators to get to a next or previous day. We can even use the subscript operator ([]) toget date fields, because of the getAt()method Groovy adds to the Date class.

The Date class also contains parse() and format()methods to convert string to a date andto format a date into a string.

// Date.parse() to convert String to Date.date = new Date().parse('yyyy/MM/dd', '1973/07/09')

// We can use [] or getAt() to get date fields.assert 1973 == date[Calendar.YEAR]assert 6 == date[Calendar.MONTH]assert 9 == date.getAt(Calendar.DATE)

dateNext = date.clone()datePrevious = date.clone()

// We can use the + and - operators to add or// subtract days.nextDay = date + 1 // Or date.plus(1)previousDay = date - 1 // Or date.minus(1)

// ++ operator to move one day ahead.dateNext++ // Or dateNext.next()assert dateNext == nextDay

// -- operator to move one day back.datePrevious-- // Or datePrevious.previous()assert datePrevious == previousDay

otherDate = new Date().parse('yyyy/MM/dd', '1973/07/21')// Dates can be used in ranges.assert 12 == (otherDate..<date).size()

// Set Locale to assert date formatting.Locale.setDefault(Locale.US)

// Date.format() uses java.text.SimpleDateFormat.assert '9 July, 1973' == date.format("d MMMM, yyyy")assert '7/9/73' == date.getDateString()

Original blog post written on August 31, 2009

Page 8: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 2

Setting Date and Calendar Values with Subscript Operators

In Groovy 1.7.3 we have some newways to set the value of Date or Calendar objects. We canfor example use the subscript operators (getAt() and putAt()methods) to define values forfields or get the value from a field. The fields are the Calendar constants like Calendar.YEAR,Calendar.DATE.

import static java.util.Calendar.*

def date = new Date()// Set value with subscript operatordate[YEAR] = 2010date[MONTH] = JUNEdate[DATE] = 14

assert 110 == date.yearassert 5 == date.monthassert 14 == date.date

// Get value with subscript operatorassert 2010 == date[YEAR]assert JUNE == date[MONTH]assert 14 == date[DATE]

def cal = Calendar.instance// Set value with subscript operatorcal[YEAR] = 2000cal[MONTH] = DECEMBERcal[DATE] = 25

assert '2000-12-25' == cal.format('yyyy-MM-dd')assert 2000 == cal[YEAR] // Get value with subscript operator

Original blog post written on June 14, 2010.

Convert Date to java.sql.Timestamp

Groovy adds many methods to standard Java classes we can use in our code. To convert asimple Date object to a java.sql.Timestamp we can simply use the toTimestamp() methodon a Date object.

Page 9: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 3

import static java.util.Calendar.*

// Create date object with specific year, month and day.def date = new Date()date.clearTime()date.set year: 2010, month: AUGUST, date: 10

// Convert to java.sql.Timestamp.def sqlTimestamp = date.toTimestamp()assert 'java.sql.Timestamp' == sqlTimestamp.class.nameassert '2010-08-10 00:00:00.0' == sqlTimestamp.toString()

Original blog post written on August 30, 2010.

Convert Date to Calendar

In Groovy version 1.7.6 we can convert a Date to a Calendarwith the toCalendar()method.The toCalendar()method is added to the Date class by Groovy.

import static java.util.Calendar.*

def date = new Date()date.set year: 2010, month: 11, date: 16

def calendar = date.toCalendar()

assert calendar[YEAR] == 2010assert calendar[MONTH] == Calendar.DECEMBERassert calendar[DATE] == 16assert calendar.format('dd-MM-yyyy') == '16-12-2010'assert calendar in Calendar

Original blog post written on December 16, 2010.

Format Dates with TimeZone

Since Groovy 1.8.3 we can use an extra TimeZone parameter with the format() method ofthe Date class. This can be used to print a date/time for a particular timezone.

import static java.util.Calendar.*

def timeZone = TimeZone.getTimeZone('Europe/Amsterdam')def otherTimeZone = TimeZone.getTimeZone('Australia/Canberra')

def cal = Calendar.instancecal.set(year: 2011, month: OCTOBER, date: 20, hourOfDay: 12, minute: 30)

def date = cal.timedef dateFormat = 'yyyy/MM/dd HH:mm'

assert date.format(dateFormat, timeZone) == '2011/10/20 12:30'assert date.format(dateFormat, otherTimeZone) == '2011/10/20 21:30'

Page 10: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 4

Original blog post written on October 20, 2011.

Parse Date.toString() Value

With Groovy 1.8.4 we can parse the output of the Date.toString() method back to a Datewith the parseToStringDate()method. For example we get the String value of a Date froman external source and want to parse it to a Date object. The format of the String musthave the pattern “EEE MMM dd HH:mm:ss zzz yyyy” with the US Locale. This is used bythe toString()method of the Date class.

import static java.util.Calendar.*

// Create date 10 November 2011.def cal = Calendar.getInstance(TimeZone.getTimeZone('Europe/Amsterdam'))def date = cal.timedate.clearTime()date[YEAR] = 2011date[MONTH] = NOVEMBERdate[DATE] = 10

// Get toString() value.def dateToString = date.toString()assert dateToString == 'Thu Nov 10 00:00:00 CET 2011'

// Replace Nov for Dec in string and 10 for 24.dateString = dateToString.replace('Nov', 'Dec').replace('10', '24')

// Use parseToStringDate to get new Date.def newDate = Date.parseToStringDate(dateString)assert newDate[MONTH] == DECEMBERassert newDate[DATE] == 24assert newDate[YEAR] == 2011

Original blog post written on November 10, 2011.

Use the set Method to Define a Date or Calendar Value

In a previous post we learned about the new subscript operator support in Groovy 1.7.3 forsetting Date or Calendar values. But we have other new ways in Groovy 1.7.3: we can usea set() method to set the values. The method accepts a Map with the following keys: year,month, date, hourOfDay, minute and second. The keys are used to set the according valuesof the Date or Calendar object.

Page 11: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 5

import static java.util.Calendar.*

def cal = Calendar.instancecal.set(year: 2010, month: JULY, date: 9)

assert 'Birthday @ 2010-7-9' == 'Birthday @ ' + cal.format('yyyy-M-d')assert FRIDAY == cal[DAY_OF_WEEK]

def date = new Date()date.set(hourOfDay: 12, minute: 0, second: 0, year: 2010, month: JUNE, date: 1)

assert '12:00:00' == date.format('HH:mm:ss')assert 2010 == date[YEAR]assert JUNE == date[MONTH]assert 1 == date.getAt(DATE)

Original blog post written on June 14, 2010.

Create New Date from Old Date with Updates

Groovy 1.7.3 adds the updated() method to the Date and Calendar classes. We pass a Mapas parameter to this method to define which fields are updated. The fields that are notmentioned are unchanged. The result is a new Date or Calendar object, our original objectstays the same.

import static java.util.Calendar.*

def cal = Calendar.instancecal[MONTH] = DECEMBERdef calNextMonth = cal.updated(month: cal[MONTH] + 1, year: 2012)

assert JANUARY == calNextMonth[MONTH]assert 2013 == calNextMonth[YEAR]

def date = new Date()date.set(year: 2011, month: MAY, date: 5)def dateTenYearsAgo = date.updated(year: date[YEAR] - 10)

assert '2011-5-5' == date.format('yyyy-M-d')assert '2001-5-5' == dateTenYearsAgo.format('yyyy-M-d')

Original blog post written on June 14, 2010.

Create New Date or Calendar from Existing and Set Property Value

Since Groovy 2.2 we can create a new Date or Calendar object from an existing Date andCalendar object and directly change property values. We must use the copyWith()methodand we pass a map with property names and values as an argument. The newly createdobject will have the old values for properties from the original object and the propertiesset in the map are overridden.

The following code shows the new copyWith()method:

Page 12: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 6

import static java.util.Calendar.NOVEMBER

// Create original date.def date = new Date().clearTime()date.set(year: 2013, month: NOVEMBER, date: 18)

// Use copyWith to get new Date and// immmediatelly set year to 2014.def yearLater = date.copyWith(year: 2014)

assert yearLater.format('dd-MM-yyyy') == '18-11-2014'

// Also works for Calendar.def cal = Calendar.instancecal.set(year: 2013, month: NOVEMBER, date: 10)

// Create new Calendar with new date value.def newCalendar = cal.copyWith(date: 18)

assert newCalendar.format('dd-MM-yyyy') == '18-11-2013'

Code written with Groovy 2.2.

Original blog post written on November 18, 2013.

Clear Time Portion of a Date

Working with dates in Groovy is easy. We get a lot of extra functionality compared to thestandard Java Date class. One of the extra methods added to the Date class since Groovy1.6.8 is clearTime(). With clearTime() we reset the time portion of a date to 12 o’clockmidnight. This makes it easier to compare dates if we only are interested in the date,month, year parts.

// Create new date.def d = new Date(year: 2010, month: Calendar.JULY, date: 1,

hours: 7, minutes: 12, seconds: 0)

assert '7/1/10 7:12:00 AM' == d.dateTimeString

// Reset time portion of the date.d.clearTime()

assert '7/1/10 12:00:00 AM' == d.dateTimeString

Original blog post written on July 1, 2010.

Date and Time Durations and the TimeCategory

Groovy has some elegant ways to work with date and time values. One of them is thesupport of durations. We can define a duration to denote a certain time amount, like 7

Page 13: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 7

days, 2 hours and 50 minutes. We can use these durations to add or subtract them fromdate and time objects.

The TimeCategory provides an even Groovier way to work with durations. We can useconstructs like 7.days + 12.minutes to create a duration. When we read this code it isjust like reading English text. Here is some sample code:

import groovy.time.*

// Define period of 2 years, 3 months, 15 days, 0 hours,// 23 minutes, 2 seconds and 0 milliseconds.def period = new DatumDependentDuration(2, 3, 15, 0, 23, 2, 0)assert '2 years, 3 months, 15 days, 23 minutes, 2.000 seconds' ==

period.toString()

def year2000 = new Date(100, 0, 0) // Jan 1, 2000assert '14 Apr 2002 22:23:02 GMT' == (period + year2000).toGMTString()

// Define time period of 5 hours, 54 minutes and 30 milliseconds.def time = new TimeDuration(5, 54, 0, 30)assert '5 hours, 54 minutes, 0.030 seconds' == time.toString()

use (TimeCategory) {assert period.toString() == (2.years + 3.months + 15.days +

0.hour + 23.minutes + 2.seconds).toString()

assert time.toString() == (5.hours + 54.minutes + 30.milliseconds).toString()

// We can use period.from.now syntax.def d1 = 1.week - 1.daydef d2 = new Date() + 6.daysassert d2.format('yyyy-MM-dd') == d1.from.now.toString()

// We can use period.ago syntax.def d3 = 3.days.agodef d4 = new Date() - 3assert d4.format('yyyy-MM-dd') == d3.toString()

}

Original blog post written on September 2, 2009

Loop Through Date and Calendar Ranges

Groovy already adds a lot of extra methods to the Date and Calendar classes. And sinceGroovy 2.2 we can use the upto() method and loop over a begin date up to another date.We pass a closure that is executed for each day.We can also iterate back using the downto()method.

Page 14: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 8

// We can loop from today// to nextWeek and invoke a closure for each day.def today = new Date().clearTime()def nextWeek = today + 7

today.upto(nextWeek) {// Print day of the week.println it.format('EEEE')

}

println()

nextweek.downto(today) {prinltn it.format('EEEE')

}

When we run the code we get the following output:

MondayTuesdayWednesdayThursdayFridaySaturdaySundayMonday

MondaySundaySaturdayFridayThursdayWednesdayTuesdayMonday

In the next sample we use the upto()method on the Calendar class:

// upto() also works on Calendar objects.def to = Calendar.instanceto.set(year: 2013, month: Calendar.NOVEMBER, date: 18)

def from = Calendar.instancefrom.set(year: 2013, month: Calendar.NOVEMBER, date: 13)

from.upto(to) {if (it[Calendar.DATE] % 2 == 0) {

print 'Even'} else {

print 'Odd'}println ' date'

}

We get the following output:

Page 15: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Dates 9

Odd dateEven dateOdd dateEven dateOdd dateEven date

Code written with Groovy 2.2.

Original blog post written on November 18, 2013.

Page 16: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps

Check if Maps are Equal

With Groovy 1.8 the equals() method is added to Map. This means we can check if mapsare equals. They are equals if both maps have the same size, and keys and values are thesame.

def map1 = [user: 'mrhaki', likes: 'Groovy', age: 37]def map2 = [age: 37.0, likes: 'Groovy', user: 'mrhaki']def map3 = [user: 'Hubert Klein Ikkink', likes: 'Groovy']

assert map1.equals(map2)assert map1 == map2assert !map1.equals(map3)assert map2 != map3

Original blog post written on April 27, 2011.

Sorting a Map

Maps don’t have an order for the elements, but wemay want to sort the entries in the map.Since Groovy 1.7.2 we can use the sort() method which uses the natural ordering of thekeys to sort the entries. Or we can pass a Comparator to the sort() method to define ourown sorting algorithm for the keys.

def m = [sort: 'asc', name: 'test', paginate: true, max: 100]

def expectedKeys = ['max', 'name', 'paginate', 'sort']

// Since 1.7.2assert expectedKeys == m.sort()*.key// Since 1.7.2assert expectedKeys == m.sort( { k1, k2 -> k1 <=> k2 } as Comparator )*.key

// Sorting before Groovy 1.7.2assert expectedKeys == new TreeMap(m)*.key

// Sort by closure.assert expectedKeys == m.sort { e1, e2 -> e1.key <=> e2.key }*.key

Original blog post written on April 20, 2010.

Page 17: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 11

Turn a List into a Map

With Groovy we can use the values of an Object array and transform them to a map withthe toSpreadMap()method. The array must have an even number of elements, because theodd elements are the keys for the new map and the even numbers are the values for thekeys. The SpreadMap object, which now contains the keys and values, is an immutable map,so we cannot change the contents once we have created the map.

def list = ['key', 'value', 'name', 'mrhaki'] as Object[]def map = list.toSpreadMap()

assert 2 == map.size()assert 'value' == map.keyassert 'mrhaki' == map['name']

Original blog post written on January 4, 2010.

Complex Keys in Maps

In Groovy we can use non-string keys for maps. We only have to place parenthesis aroundthe key to make it work. This way we can use variables and types like Date and Boolean askeys for our map. When we use parenthesis around the key when using the . notation thekey is converted to a String, otherwise the key is not converted and keeps it type.

def key = 100 // Variable to be used a key.

def m = [(new Date(109, 11, 1)): 'date key',(-42): 'negative number key',(false): 'boolean key',(key): 'variable key'

]m.(true) = 'boolean key' // Key is converted to String.m.(2 + 2) = 'number key'm[(key + 1)] = 'number key' // Key keeps to be Integer.

assert 'date key' == m[new Date(109, 11, 1)]assert 'negative number key' == m.get(-42)assert 'boolean key' == m[(false)]assert 'variable key' == m[100]assert 'variable key' == m.getAt(key)// Key is String so we can use it to get the value.assert 'boolean key' == m['true']assert 'number key' == m.'4'assert 'number key' == m.get(101)

Original blog post written on November 7, 2009

Page 18: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 12

Use inject Method on a Map

The inject() method is since Groovy 1.8.1 also available for Map objects. The closurearguments accepts two or three arguments. With the three-argument variant we get thekey and value separately as arguments. Otherwise we get amap entry as closure argument.

// 3-argument closure with key, value.def m = [user: 'mrhaki', likes: 'Groovy']def sentence = m.inject('Message: ') { s, k, v ->

s += "${k == 'likes' ? 'loves' : k} $v "}

assert sentence.trim() == 'Message: user mrhaki loves Groovy'

// 2-argument closure with entry.def map = [sort: 'name', order: 'desc']def equalSizeKeyValue = map.inject([]) { list, entry ->

list << (entry.key.size() == entry.value.size())}

assert equalSizeKeyValue == [true, false]

Original blog post written on September 27, 2011.

Intersect Maps

Since Groovy 1.7.4 we can intersect two maps and get a resulting map with only the entriesfound in both maps.

def m1 = [a: 'Groovy', b: 'rocks', c: '!']def m2 = [a: 'Groovy', b: 'rocks', c: '?', d: 'Yes!']

assert [a: 'Groovy', b: 'rocks'] == m1.intersect(m2)

assert [1: 1.0, 2: 2] == [1: 1.0, 2: 2].intersect([1: 1, 2: 2.0])

Original blog post written on August 9, 2010.

Subtracting Map Entries

Groovy 1.7.4 adds the minus() method to the Map class. The result is a new map with theentries of the map minus the same entries from the second map.

Page 19: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 13

def m1 = [user: 'mrhaki', age: 37]def m2 = [user: 'mrhaki', name: 'Hubert']def m3 = [user: 'Hubert', age: 37]

assert [age: 37] == m1 - m2assert [user: 'mrhaki'] == m1 - m3

Original blog post written on August 9, 2010.

Process Map Entries in Reverse

Since Groovy 1.7.2 we can loop through a Map in reverse with the reverseEach(). The orderin which the content is processed is not guaranteed with a Map. If we use a TreeMap thenatural ordering of the keys of the map is used.

def reversed = [:][a: 1, c: 3, b: 2].reverseEach { key, value ->

reversed[key] = value ** 2}

assert [b: 4, c: 9, a: 1] == reversed

// TreeMap uses natural ordering of keys, so// reverseEach starts with key 'c'.def tree = [a: 10, c: 30, b: 20] as TreeMapdef reversedMap = [:]tree.reverseEach {

reversedMap[it.key] = it.value * 2}assert [c: 60, b: 40, a: 20] == reversedMap

Original blog post written on August 24, 2010.

Getting a Submap from a Map

To get only a subset of a map we can use the subMap()method. We provide a list of keys asparameter to define which elements from the map we want returned.

def map = [name: 'mrhaki', country: 'The Netherlands',blog: true, languages: ['Groovy', 'Java']]

def keys = ['name', 'blog']assert [name: 'mrhaki', blog: true] == map.subMap(keys)

def booleanKeys = map.findAll { it.value instanceof Boolean }.collect { it.key }

assert [blog: true] == map.subMap(booleanKeys)

def words = ['a': 'Apple', 'j': 'Java', 'g': 'Groovy', 'c': 'Cool']def range = 'c'..'h' // Range is also a list and can be used here.

Page 20: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 14

def rangeWords = words.subMap(range).findAll{ it.value }

// words.subMap(range) returns [c:Cool, d:null, e:null,// f:null, g:Groovy, h:null]// so we use the findAll method to filter out all null values.assert ['c': 'Cool', 'g': 'Groovy'] == rangeWords

Original blog post written on October 29, 2009

Grouping Map Elements

In a previous post we learned how to use the groupBy() method on collections. The Mapclass has an extra method: groupEntriesBy(). We must provide a closure for this methodto define how we want the elements of the map to be grouped. The result is a new Mapwith keys and a list of Map$Entry objects for each key. This is different from the result ofthe groupBy()method. Because then we get a Map with keys and a Map for each key.

// A simple map.def m = [q1: 'Groovy', sort: 'desc', q2: 'Grails']

// Closure we use to define the grouping.// We want all keys starting with 'q' grouped together// with the key 'params', all other keys are not grouped.def groupIt = { key, value ->

if (key.startsWith('q')) {'params'

} else {key

}}

// Use groupEntriesBy.def groupEntries = m.groupEntriesBy(groupIt)assert 2 == groupEntries.size()assert groupEntries.paramsassert groupEntries.sort// Key for a list of Map$Entry objects.assert 'desc' == groupEntries.sort[0].valueassert 2 == groupEntries.params.size()assert 'Groovy' == groupEntries.params[0].valueassert 'q1' == groupEntries.params[0].keyassert 'Grails' == groupEntries.params.find { it.key == 'q2' }.valueassert groupEntries.params instanceof ArrayListassert groupEntries.params[0] instanceof Map$Entry

// Use groupBy.def group = m.groupBy(groupIt)assert 2 == group.size()assert group.paramsassert group.sort// Key for Map with key/value pairs.assert 'desc' == group.sort.sortassert 2 == group.params.size()

Page 21: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 15

assert 'Groovy' == group.params.q1assert 'q1' == group.params.keySet().toArray()[0]assert 'Grails' == group.params.q2assert group.params instanceof Mapassert group.params.q1 instanceof String

Original blog post written on October 14, 2009

Get Value from Map or a Default Value

The get()method in the Groovy enhanced Map interface accepts two parameters. The firstparameter is the name of the key we want to get a value for. And the second parameter isthe default value if there is no value for the key.

// Simple map.def m = [name: 'mrhaki', language: 'Groovy']

assert 'mrhaki' == m.getAt('name')assert 'mrhaki' == m['name']assert 'Groovy' == m.languageassert 'mrhaki' == m."name"assert 'mrhaki' == m.get('name') // We can omit the default value if we know the key exists.assert 'Groovy' == m.get('language', 'Java')assert null == m.get('expression') // Non-existing key in map.assert 'rocks' == m.get('expression', 'rocks') // Use default value, this also creates the key/v\alue pair in the map.assert 'rocks' == m.get('expression')assert [name: 'mrhaki', language: 'Groovy', expression: 'rocks'] == m

Original blog post written on November 3, 2009

Map with Default Values

In Groovy we can create a map and use the withDefault()method with a closure to definedefault values for keys that are not yet in the map. The value for the key is then added tothe map, so next time we can get the value from the map.

def m = [start: 'one'].withDefault { key ->key.isNumber() ? 42 : 'Groovy rocks!'

}

assert 'one' == m.startassert 42 == m['1']assert 'Groovy rocks!' == m['I say']assert 3 == m.size()

// We can still assign our own values to keys of course:m['mrhaki'] = 'Hubert Klein Ikkink'assert 'Hubert Klein Ikkink' == m.mrhakiassert 4 == m.size()

Original blog post written on July 14, 2010.

Page 22: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 16

Determine Min and Max Entries in a Map

Since Groovy 1.7.6 we can use the min() and max() methods on a Map. We use a closure todefine the condition for a minimum or maximum value. If we use two parameters in theclosure we must do a classic comparison. We return a negative value if the first parameteris less than the second, zero if they are equal, or a positive value if the first parameter isgreater than the second parameter. If we use a single parameter we can return a value thatis used as Comparable for determining the maximum or minimum entry in the Map.

def money = [cents: 5, dime: 2, quarter: 3]

// Determine max entry.assert money.max { it.value }.value == 5

// Use String comparison for key.assert money.max { it.key }.key == 'quarter'

// Use Comparator and compare key size.assert money.max { a, b ->

a.key.size() <=> b.key.size()}.key == 'quarter'

// Determine min entry.assert money.min { it.value }.value == 2

// Use String comparison for key.assert money.min { it.key }.key == 'cents'

// Use Comparator and compare key size.assert money.min { a, b ->

a.key.size() <=> b.key.size()}.key == 'dime'

Original blog post written on December 16, 2010.

Represent Map As String

Groovy adds to Map objects the toMapStringmethod.With thismethodwe can have a Stringrepresentation of our Map. We can specify an argument for the maximum width of thegenerated String. Groovy will make sure at least the key/value pairs are added as a pair,before adding three dots (...) if the maximum size is exceeded.

def course = [name: 'Groovy 101',teacher: 'mrhaki',location: 'The Netherlands']

assert course.toMapString(15) == '[name:Groovy 101, ...]'assert course.toMapString(25) == '[name:Groovy 101, teacher:mrhaki, ...]'

As mentioned in a previous post we can use the toListStringmethod to represent a Listas a String:

Page 23: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 17

def names = ['mrhaki', 'hubert']

assert names.toListString(5) == '[mrhaki, ...]'

Written with Groovy 2.4.7.

Original blog post written on June 21, 2016.

Turn A Map Or List As String To Map Or List

In a previous post we learned how to use the toListString or toMapStringmethods. Withthese methods we create a String representation of a List or Map object. With a bit ofGroovy code we can take such a String object and turn it into a List or Map again.

In the following code snippet we turn the String value [abc, 123, Groovy rocks!] to aList with three items:

// Original List with three items.def original = ['abc', 123, 'Groovy rocks!']

// Create a String representation:// [abc, 123, Groovy rocks!]def listAsString = original.toListString()

// Take the String value between// the [ and ] brackets, then// split on , to create a List// with values.def list = listAsString[1..-2].split(', ')

assert list.size() == 3assert list[0] == 'abc'assert list[1] == '123' // String valueassert list[2] == 'Groovy rocks!'

We can do something similar for a String value representing a map structure:

// Original Map structure.def original = [name: 'mrhaki', age: 42]

// Turn map into String representation:// [name:mrhaki, age:42]def mapAsString = original.toMapString()

def map =// Take the String value between// the [ and ] brackets.mapAsString[1..-2]

// Split on , to get a List..split(', ')// Each list item is transformed// to a Map entry with key/value.

Page 24: Groovy Goodness Notebook - Leanpubsamples.leanpub.com/groovy-goodness-notebook-sample.pdf · Dates 3 import static java.util.Calendar.* // Create date object with specific year, month

Maps 18

.collectEntries { entry ->def pair = entry.split(':')[(pair.first()): pair.last()]

}

assert map.size() == 2assert map.name == 'mrhaki'assert map.age == '42'

Written with Groovy 2.4.7.

Original blog post written on June 22, 2016.