I have a Java code that looks like below code:
for(MyClass myclassObject: input.classes()) {
if(myclassObject.getName().equals("Tom")) {
outputMap.put("output", myclassObject.getAge())
}
}
How do I efficiently write this with Groovy collectmap?
I can do
input.classes().collectEntries["output":it.getAge()] But how do I include the if condition on it?
you could use findAll to keep only items according to condition
and after then apply collectEntries to transform items found
#groovy.transform.ToString
class MyClass{
int age
String name
}
def classes = [
new MyClass(age:11, name:'Tom'),
new MyClass(age:12, name:'Jerry'),
]
classes.findAll{it.getName()=='Tom'}.collectEntries{ [output:it.getAge()] }
Since your resulting map is only retaining one value anyway, you can also just do this:
input.classes().findResult { it.name == 'Tom' ? [output: it.age] : null }
where findResult will return the first item in classes() for which the closure:
{ it.name == 'Tom' ? [output: it.age] : null }
returns a non-null value.
Since you mentioned efficiency in your question: this is more efficient than going through the whole collection using collectEntries or findAll since findResult returns directly on finding the first instance of it.name == 'Tom'.
Which way to go really depends on your requirements.
collectEntries can take a closure as a parameter. You can apply your logic inside the closure and make sure you return the Map Entry when condition passes and return an empty map when condition fails. Therefore;
input.classes().collectEntries { MyClass myClassObject ->
myClassObject.name == 'Tom' ? ['output': myClassObject.getAge()] : [:]
}
However, with your approach there is a caveat. Since you are using the key as output and Map does not allow duplicate keys, you will always end up with the last entry in the map. You have to come up with a better plan if that is not your intention.
Related
I'm trying to generate HashMap object that will have properties and values set from parsed text input. Working fine with simple assigned, but wanted to make it more clever and use inject.
def result = new HashMap();
def buildLog = """
BuildDir:
MSBuildProjectFile:test.csproj
TargetName: test
Compile:
Reference:
""".trim().readLines()*.trim()
buildLog.each {
def (k,v) = it.tokenize(':')
result."${k.trim()}"=v?.trim()
}
println "\nResult:\n${result.collect { k,v -> "\t$k='$v'\n" }.join()}"
generates expected output:
Result:
Reference='null'
MSBuildProjectFile='test.csproj'
BuildDir='null'
TargetName='test'
Compile='null'
after replacing the insides of .each { } closure with injection:
it.tokenize(':').inject({ key, value -> result."${key}" = value?.trim()})
the results generated are missing unset values
Result:
MSBuildProjectFile='test.csproj'
TargetName='test'
Am I doing something wrong, tried with inject ("", {...}) but it seems to push may keys into values.
inject is basically a reduce. The reducing function takes two arguments, the result of the previous iteration or the initial value (e.g. the accumulator) and the next value from the sequence. So it could be made to work, but since you only expect one sequence value, it just convolutes the code.
I do see a great use for collectEntries here, as it allows you to create a Map using either small key/values map, or lists of two elements. And the latter you have:
result = buildLog.collectEntries {
it.split(":",2)*.trim()
}
should work for your code instead of buildLog.each
I am trying to get a class, which combines list, set and map in Kotlin. I wished to write isScalar function, which should return true if object contains only one element and wrote
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap
import it.unimi.dsi.fastutil.objects.ReferenceArrayList
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
class Args {
var list : ReferenceArrayList<M>? = null
var set : ReferenceOpenHashSet<M>? = null
var map : Reference2ReferenceOpenHashMap<M, M>? = null
fun isEmpty() : Boolean {
return list === null && set === null && map === null
}
fun isScalar() : Boolean {
if(list !== null && list.size == 1) {
return true
}
}
}
Unfortunately it gave me error in comparison
list !== null && list.size == 1
saying
Smart cast to 'ReferenceArrayList<M>' is impossible, because 'list' is a mutable property that could have been changed by this time
As far as I understood, this is related with multithreaded assumption. In Java I would make function synchronized if would expect multithreding. Also, I would be able to disregard this at all, if I am not writing thread-safe.
How should I write in Kotlin?
I saw this solution https://stackoverflow.com/a/44596284/258483 but it expects MT, which I don't want to. How to avoid smart casting if it can't do it?
UPDATE
The question is how to do this in the same "procedural" form. How not to use smart casting?
UPDATE 2
Summarizing, as far as I understood, it is not possible/reasonable to explicitly compare variable with null in Kotlin at all. Because once you compare it, next time yous hould compare it with null again implicitly with such operations like .? and you can't avoid this.
If you take advantage of the fact that null cannot equal 1 (or anything else, really), you can make this check very concise:
fun isScalar() : Boolean =
list?.size == 1
When a null-safe call to list.size returns null, we get false because 1 != null. Otherwise, a comparison of whatever value size returns is made, and that works as you would expect.
By using the null safe operator (?.) you are avoiding a smart cast entirely. Kotlin gives us smart casts to make code cleaner, and this is one of the ways it protects us from misuses of that feature. Kotlin isn't going to protect us from everything (division by zero, the example you use in comments, for example). Your code is getting caught up in a legitimate case of where smart casting can go wrong, so Kotlin jumps in to help.
However, if you are absolutely sure there are no other threads working, then yes, this check is "wrong". You wouldn't need the warning in that case. Judging by this thread on kotlinlang.org, you aren't the only one!
You can perform the null check, and if it succeeds, access a read-only copy of your variable with let:
fun isScalar() : Boolean {
return list?.let { it.size == 1 } ?: false
}
If list is null, the entire let expression will evaluate to null, and the right side of the Elvis operator (false) will be returned.
If list is not null, then the let function is called, and result of the it.size == 1 expression is returned - it refers to the object that let was called on (list in this case). Since it's used with a safe call, this it will have a non-nullable type and size can be called on it.
I had the same problem in the given lines
sliderView.setSliderAdapter(adapter!!)
sliderView.setIndicatorAnimation(IndicatorAnimationType.WORM)
Finally, error resolved by adding !!
sliderView!!.setSliderAdapter(adapter!!)
sliderView!!.setIndicatorAnimation(IndicatorAnimationType.WORM)
Does any common Java library provide a method to find an element in a finite collection and ensure that there was exactly one match?
The method could, for example, return null if nothing was found and throw an exception if multiple elements were found.
Currently I use my own Implementation (see below), but I'd rather not pollute business code with such utility methods (even if extracted in a separate utility package).
I also don't want the overhead of iterating over collection more than once, or an overhead of filtering collection and looking at the length of the result.
P.S. my current solution (which works, but is to be replaced with a library method):
public static <T> T getSingleMatch(Iterable<T> lookIn, com.google.common.base.Predicate<? super T> predicate) {
T foundItem = null;
for (T item : lookIn) {
if (predicate.apply(item)) {
if (foundItem != null)
throw new RuntimeException("multiple matches"); // alternatively: `return null;`
else
foundItem = item;
}
}
// alternatively: `if (foundItem == null) throw ...`
return foundItem;
}
One option is to separate out the two ideas into two methods, so that each method does one thing - then combine the calls
One method to lazily filter, returning a sequence of matching results
One method to return an item from a sequence, requiring it to be the only item
Guava has both of those:
Iterables.filter to filter lazily
Iterables.getOnlyElement to return the sole element of a sequence
So for example:
String match = Iterables.getOnlyElement(Iterables.filter(source, predicate));
int index = collection.indexOf(item);
if (index != -1 && index == collection.lastIndexOf(item)) {
// one and only one
}
If index != -1 it means no such item. If the next if statement doesn't evaluate to true it means that there are at least 2 items. You can restructure it to throw exceptions, return null or return the index or item. I trust you know how to do this based on your question.
I got confused with this two lines of coding :
this.class.methods.name
This is called Gpath (Am I right?). Now consider this code :
count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }.each { count ++ }
println count
The line:
a.findAll { it == 5 }.each { count ++ }
is called as a method chaining or Gpath?
Literally, I got struck with these two meanings. It will be nice if some one explains the difference between these two.
Thanks in advance.
I'm not sure if I understand the question correctly.
As I see it, in both examples you are using method chaining, simply because you are calling a method in the object that is returned by another method. But, as Arturo mentions, some people confuse method chaining and fluent interfaces. A fluent interface is indeed quite handy if you want to chain methods.
In Groovy, however, you may, instead of coding a fluent interface yourself, use the with method in any object. For example, using the same Person and Address classes that Arturo defined, you can do:
def person = new Person()
person.with {
name = 'John'
age = 25
address = new Address('Boulevard St')
}
assert person.name == 'John' &&
person.age == 25 &&
person.address.name == 'Boulevard St'
Now, GPath, as I understand, is just a way of accessing the properties of an object. For example, if you have the class:
class Foo {
def bar
}
The GPath mechanism in Groovy lets you do things like:
def foo = new Foo(bar: 42)
assert foo.bar == 42
Instead of accessing the bar property with its getter, like foo.getBar(). Nothing too fancy. But other classes in Groovy also have some GPath magic and there is where things get more interesting. For example, lists let you access properties in their elements the same way you'd access normal properties:
def foos = (1..5).collect { new Foo(bar: it) } // Five Foos.
assert foos.bar == [1, 2, 3, 4, 5]
As you can see, accessing the bar property on a list of objects that have that property will result in a list with the values of that property for each object in the list. But if you access a property that the elements of the list don't have, e.g. foos.baz, it will throw a MissingPropertyException.
This is exactly what is happening in:
this.class.methods.name
I, however, consider this behavior to be a little too magic for my taste (unless you are parsing XML, in which case is totally fine). Notice that if the collection returned by the methods method would be some weird collection that had a name property, methods.name would result in that name instead of the names of each method in the collection. In these cases I prefer to use the (IMO) more explicit version:
this.class.methods*.name
Wich will give you the same result, but it's just syntax sugar for:
this.class.methods.collect { it.name }
... and let's the intention of the expression to be more clear (i.e. "I want the names of each method in methods").
Finally, and this is quite off-topic, the code:
count = 0
def a = [1,2,3,4,5,5,51,2]
a.findAll { it == 5 }.each { count ++ }
println count
can be rewritten as:
def a = [1,2,3,4,5,5,51,2]
def count = a.count { it == 5 }
println count
:)
I think that your code is an example of method chaining.
GPath is a path expression language integrated into Groovy which allows to navigate in XML or POJOs. You can perform nested property access in objects.
Method chaining is a technique for invoking multiple method calls in object-oriented programming languages. Each method returns an object (possibly the current object itself), allowing the calls to be chained together in a single statement.
I'm going to use an example with TupleConstructor to assist in the creation of the object.
import groovy.transform.TupleConstructor
#TupleConstructor
class Address {
String name
}
#TupleConstructor
class Person {
String name
Integer age
Address address
}
def person = new Person('John', 25, new Address('Boulevard St'))
Ok, you are right, this access is called GPath:
assert person.address.name == 'Boulevard St'
A getter access could be named method chaining:
assert person.getAddress().getName() == 'Boulevard St'
But what happens if I can do something like this:
person.setName('Louise')
.setAge(40)
.setAddress(new Address('Main St'))
I need to create a fluent API, an method chaining is the way, the idea is to let methods return this rather than void.
#TupleConstructor
class Person {
String name
Integer age
Address address
def setName(name) {
this.name = name
return this
}
def setAge(age) {
this.age = age
return this
}
}
I am new to groovy and I've been facing some issues understanding the each{} and eachwithindex{} statements in groovy.
Are each and eachWithIndex actually methods? If so what are the arguments that they take?
In the groovy documentation there is this certain example:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" } //prints each index and number
Well, I see that numbers is an array. What are num and idx in the above statement? What does the -> operator do?
I do know that $idx and $num prints the value, but how is it that idx and num are automatically being associated with the index and contents of the array? What is the logic behind this? Please help.
These are plain methods but they follow quite a specific pattern - they take a Closure as their last argument. A Closure is a piece of functionality that you can pass around and call when applicable.
For example, method eachWithIndex might look like this (roughly):
void eachWithIndex(Closure operation) {
for (int i = 0; this.hasNext(); i++) {
operation(this.next(), i); // Here closure passed as parameter is being called
}
}
This approach allows one to build generic algorithms (like iteration over items) and change the concrete processing logic at runtime by passing different closures.
Regarding the parameters part, as you see in the example above we call the closure (operation) with two parameters - the current element and current index. This means that the eachWithIndex method expects to receive not just any closure but one which would accept these two parameters. From a syntax prospective one defines the parameters during closure definition like this:
{ elem, index ->
// logic
}
So -> is used to separate arguments part of closure definition from its logic. When a closure takes only one argument, its parameter definition can be omitted and then the parameter will be accessible within the closure's scope with the name it (implicit name for the first argument). For example:
[1,2,3].each {
println it
}
It could be rewritten like this:
[1,2,3].each({ elem ->
println elem
})
As you see the Groovy language adds some syntax sugar to make such constructions look prettier.
each and eachWithIndex are, amongst many others, taking so called Closure as an argument. The closure is just a piece of Groovy code wrapped in {} braces. In the code with array:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" }
there is only one argument (closure, or more precisely: function), please note that in Groovy () braces are sometime optional. num and idx are just an optional aliases for closure (function) arguments, when we need just one argument, this is equivalent (it is implicit name of the first closure argument, very convenient):
def numbers = [ 5, 7, 9, 12 ]
numbers.each {println "$it" }
References:
http://groovy.codehaus.org/Closures
http://en.wikipedia.org/wiki/First-class_function
Normally, if you are using a functional programing language such as Groovy, you would want to avoid using each and eachWithIndex since they encourage you to modify state within the closure or do things that have side effects.
If possible, you may want to do your operations using other groovy collection methods such as .collect or .inject or findResult etc.
However, to use these for your problem, i.e print the list elements with their index, you will need to use the withIndex method on the original collection which will transform the collection to a collection of pairs of [element, index]
For example,
println(['a', 'b', 'c'].withIndex())
EachWithIndex can be used as follows:
package json
import groovy.json.*
import com.eviware.soapui.support.XmlHolder
def project = testRunner.testCase.testSuite.project
def testCase = testRunner.testCase;
def strArray = new String[200]
//Response for a step you want the json from
def response = context.expand('${Offers#Response#$[\'Data\']}').toString()
def json = new JsonSlurper().parseText(response)
//Value you want to compare with in your array
def offername = project.getPropertyValue("Offername")
log.info(offername)
Boolean flagpresent = false
Boolean flagnotpresent = false
strArray = json.Name
def id = 0;
//To find the offername in the array of offers displayed
strArray.eachWithIndex
{
name, index ->
if("${name}" != offername)
{
flagnotpresent= false;
}
else
{
id = "${index}";
flagpresent = true;
log.info("${index}.${name}")
log.info(id)
}
}