Search

Dark theme | Light theme
Showing posts with label Groovy:Goodness GroovyGoodness:GDK. Show all posts
Showing posts with label Groovy:Goodness GroovyGoodness:GDK. Show all posts

February 12, 2020

Groovy Goodness: Calculate Average For Collection

Groovy 3 adds the average method to collections to calculate the average of the items in the collections. When the items are numbers simply the average is calculated. But we can also use a closure as argument to transform an item into a number value and then the average on that number value is calculated.

In the following example code we use the average method on a list of numbers and strings. And we use a closure to first transform an element before calculating the average:

def numbers = [10, 20, 30, 40, 50]

assert numbers.average() == 30

// We can use a closure to transform an item
// and the result is used for calculating an average.
assert numbers.average { n -> n / 10 } == 3


def words = ['Groovy', 'three', 'is', 'awesome']

// Use supported Java method reference syntax to first 
// get length of word.
assert words.average(String::size) == 5

// Calculate average number of vowels in the words.
assert words.average { s -> s.findAll(/a|e|i|o|u/).size() } == 2.25

Written with Groovy 3.0.0.

March 19, 2015

Groovy Goodness: Use Constructor as Method Pointer

In Java 8 we can create a constructor reference. We must use the syntax Class::new and we get a constructor reference. This syntax is not supported in Groovy, but we can use the method pointer or reference syntax .& to turn a method into a closure. We can even turn a constructor into a closure and use it everywhere where closures are allowed.

In the following sample code we have a User class with some properties. Via the User.metaClass we can get a reference to the method invokeConstructor and turn it into a method closure:

@groovy.transform.Immutable
class User {
    String name
    int age
}


// Initial list with user defined
// using a map or Object array.
def userList = [
    // User defined as map, keys
    // are properties of User class.
    [name: 'mrhaki', age: 41], 
    
    // Object array with name and
    // age properties for User class.
    ['john', 30] as Object[]
]

// Create constructor reference.
// Result is a closure we can use in our code.
def createUser = User.metaClass.&invokeConstructor

// Invoke the collect method with our
// constructor reference. At the end
// all elements of the userList 
// are converted to new User objects.
def users = userList.collect(createUser)


assert users.name == ['mrhaki', 'john']
assert users.age == [41, 30]

Code written with Groovy 2.4.1.

April 3, 2014

Groovy Goodness: Converting Byte Array to Hex String

To convert a byte[] array to a String we can simply use the new String(byte[]) constructor. But if the array contains non-printable bytes we don't get a good representation. In Groovy we can use the method encodeHex() to transform a byte[] array to a hex String value. The byte elements are converted to their hexadecimal equivalents.

final byte[] printable = [109, 114, 104, 97, 107, 105]

// array with non-printable bytes 6, 27 (ACK, ESC)
final byte[] nonprintable = [109, 114, 6, 27, 104, 97, 107, 105]


assert new String(printable) == 'mrhaki'
assert new String(nonprintable) != 'mr  haki'


// encodeHex() returns a Writable
final Writable printableHex = printable.encodeHex()
assert printableHex.toString() == '6d7268616b69'
final nonprintableHex = nonprintable.encodeHex().toString()
assert nonprintableHex == '6d72061b68616b69'


// Convert back
assert nonprintableHex.decodeHex() == nonprintable

Code written with Groovy 2.2.1

November 20, 2013

Groovy Goodness: Enhancements for Iterable Implementations

Since Groovy 2.2 a lot of the useful methods that are added to the collection API interfaces are also available for classes implementing the Iterable interface:

// Counter is implementation for Iterable interface.
class Counter implements Iterable {
    Integer maxValue
    private Integer counter = 0
    
    // Return new Iterator instance.
    @Override
    Iterator iterator() {
        [hasNext: { counter <= maxValue }, 
         next: { counter++ }] as Iterator
    }
    
}

assert counter.sum() == 55
assert counter.min() == 0
assert counter.max() == 10
assert counter.count(2) == 1
assert counter.count { it % 2 == 0 } == 6
assert counter.collectMany { [it * 2] } == [0,2,4,6,8,10,12,14,16,18,20]
assert counter.groupBy { it % 4 == 0 ? 'fours' : 'noneFours' } == [fours: [0,4,8], noneFours: [1,2,3,5,6,7,9,10]]

private getCounter() {
    new Counter(maxValue: 10)
}

September 6, 2013

Groovy Goodness: Replace Characters in a String with CollectReplacements

We can use the collectReplacements(Closure) method to replace characters in a String. We pass a closure to the method and the closure is invoked for each character in the String value. If we return null the character is not transformed, otherwise we can return the replacement character.

def s = 'Gr00vy is gr8'

def replacement = {
    // Change 8 to eat
    if (it == '8') {
        'eat'
    // Change 0 to o
    } else if (it == '0') {
        'o'
    // Do not transform
    } else {
        null
    }
}

assert s.collectReplacements(replacement) == 'Groovy is great'

Code written with Groovy 2.1.6

January 28, 2013

Groovy Goodness: Append Values to Appendable Objects

Since Groovy 2.1 we have a couple of extra methods available for objects that implement the java.lang.Appendable interface. A lot of Writer objects implement this interface. The documentation of the Appendable interface mentions: An object to which char sequences and values can be appended.

First the leftShift() method is added. This means we can use the leftShift operator (<<) to append a value. Then we also can use the withFormatter() method. We can pass a closure to this method or a java.util.Locale object and a closure. The closure has a single parameter which is a java.util.Formatter instance. We can use this method to add printf-style formatted strings to an Appendable object. If we pass a Locale object to the method the Formatter is created with the specified Locale to created localized printf-sytle formatted strings.

// Create object that implements the Appendable interface.
final Appendable appendable = new StringWriter()

assert appendable in Appendable


// Use leftShift operator to add to Appendable implementation.
appendable << 'Groovy is Gr8!' << newLine


// Use withFormatter() method.
// Formatter object 
// is passed to closure as parameter.
appendable.withFormatter { formatter ->
    // Simple formatter pattern to reorder the arguments.
    formatter.format(/m r %3$1s %2$1s %1$1s %4$1s%n/, 'k', 'a', 'h', 'i')
}


// Use withFormatter() method and use Locale object
// as extra argument. The Locale is passed on
// to create the Formatter object.
appendable.withFormatter(Locale.US) { formatter ->
    formatter.format("US: " + datePattern, date)
}
// Use different Locale.
appendable.withFormatter(new Locale('nl')) { formatter ->
    formatter.format("Dutch: $datePattern", date)
}


// Check result is as expected:
assert appendable.toString() == '''Groovy is Gr8!
m r h a k i
US: January 27, 2013
Dutch: januari 27, 2013
'''


// Helper getters:

String getNewLine() {
    System.getProperty('line.separator')
}

Date getDate() {
    // Simple date to use in withFormatter() methods.
    Date.parse('yyyy-MM-dd', '2013-01-27')
}

String getDatePattern() {
    // Date pattern for Formatter.
    '%1$tB %1$te, %1$tY%n'
}

Code written with Groovy 2.1

October 2, 2012

Groovy Goodness: Drop or Take Elements with Condition

In Groovy we can use the drop() and take() methods to get elements from a collection or String object. Since Groovy 1.8.7 we also can use the dropWhile() and takeWhile() methods and use a closure to define a condition to stop dropping or taking elements. With the dropWhile() method we drop elements or characters until the condition in the closure is true. And the takeWhile() method returns elements from a collection or characters from a String until the condition of the closure is true.

In the following example we see how we can use the methods:

def s = "Groovy Rocks!"

assert s.takeWhile { it != 'R' } == 'Groovy '
assert s.dropWhile { it != 'R' } == 'Rocks!'


def list = 0..10

assert 0..4 == list.takeWhile { it < 5 }
assert 5..10 == list.dropWhile { it < 5 }


def m = [name: 'mrhaki', loves: 'Groovy', worksAt: 'JDriven']

assert [name: 'mrhaki'] == m.takeWhile { key, value -> key.length() == 4 }
assert [loves: 'Groovy', worksAt: 'JDriven'] == m.dropWhile { it.key == 'name' }

(Code is written with Groovy 2.0.4)

September 25, 2012

Groovy Goodness: Boolean Implications

Since Groovy 1.8.3 we can use the implies() method on Boolean types. The implies() method implements a logical implication. This means that if we have two Boolean variables A and B, that if A is true, then B is true. So if A is true then it is implied B is true as well. If A is false then B can be either true or false. We could rewrite the implication as !A or B.

def a = true
def b = true

assert a.implies(b)
assert !(a.implies(false))

assert a.implies(b) == ((!a).or(b))

assert true.implies(true)
assert false.implies(true)
assert false.implies(false)
assert !true.implies(false)

(Code written with Groovy 2.0.4)

April 27, 2011

Groovy Goodness: Add Items to a List at Specified Position

Since Groovy 1.8 we can create a new list from two lists, where the second list is 'inserted' at a specified index position in the first list. The original lists are not changed: the result is a new list. Groovy also adds the addAll() method to List objects (since Groovy 1.7.2), but then the original list object is changed.

def list = ['Gr', 'vy']

assert list.plus(1, 'oo') == ['Gr', 'oo', 'vy']
assert list == ['Gr', 'vy']

list.addAll(1, 'oo') 
assert list == ['Gr', 'oo', 'vy']

assert (1..10).plus(5, 6..7) == [1,2,3,4,5,6,7,6,7,8,9,10]