Upload
others
View
9
Download
2
Embed Size (px)
Citation preview
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)
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
Also By Hubert A. Klein Ikkink (mrhaki)Grails Goodness Notebook
Gradle Goodness Notebook
Spocklight Notebook
Awesome Asciidoctor Notebook
Ratpacked Notebook
This book is dedicated to my lovely family. I love you.
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
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
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.
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'
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.
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:
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
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.
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:
Dates 9
Odd dateEven dateOdd dateEven dateOdd dateEven date
Code written with Groovy 2.2.
Original blog post written on November 18, 2013.
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.
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
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.
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.
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()
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.
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:
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.
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.