Get delegate function for arbitrary java method - java

Is there an easy way to get an arbitrary Function version of a method on a POJO?
For example:
FluentIterable.from(myCollection).uniqueIndex(Functions.for(Item.class).getId)
.first(Predicates.equalTo(id)).get();
Where Functions.for ideally behaves like Mockito.mock

Actually you can use lambdaj which is
a library that makes easier to address this issue by allowing to
manipulate collections in a pseudo-functional and statically typed
way.
Lambdaj does similar tricks as Mockito, so you should read its limitations (most important is that your POJO must not be final).
With lambdaj, your code could be something like this (note that uniqueIndex from your example returns Map, which does not have first method, so I'll guess here):
import ch.lambdaj.Lambda.*; // for all static methods used below
// just items indexed by their ids
Map<Intgeger, Item> indexed = index(myCollection, on(Item.class).getId());
// or more likely you want
Item foundItem = selectFirst(
myCollection, having(on(Item.class).getId(), equalTo(id)));

That's not how Java works.
However, with Java 8, you can use a method reference to create a lambda:
FluentIterable.from(myCollection).uniqueIndex(Item::getId)
.first(Predicates.equalTo(id)).get();

Related

Custom accessor strategy for Clojure `from-java`

Is there any way to customise the accessor strategy used in clojure.java.data/from-java? from-java is part of the java.data function lib.
I recently updated a third-pary Java-library that used to follow the JavaBean get and set pattern. However, after the update they went from getProperty() to property()...
I guess this change renders the from-java function not suitable in this case, no surprise since the objects are no longer proper JavaBeans.
Is there any way of making from-java aware of this accessor-pattern, or are there any other recursive mapping-mechanisms that supports this?
from-java is a multimethod, do you can override it for any class you like. There is no mechanism for teaching it an alternate naming convention (and if there were such a mechanism, I imagine it would have trouble with "every method with any name at all represents a property"). Therefore you'll have to write manual conversions, but at least the recursion will be handled for you.
It seems you will have to extend the multimethod to support the classes yourself, however, you can probably use reflection (slow, I know) to build something very generic:
For a given object instance, find its class, then the class' DeclaredFields, and from each fields get their name and type
For the same instance, use .getDeclaredMethod or .getDeclaredMethods to find methods for the given name that take no params (use an empty array for this). Those methods should be the new "getters" and you can call these in your instance to extract the values.
Use the Cognitect aws-api instead :)

Using scala object inside java?

In my java code, I am calling a method, from a class which is defined in Scala, and I want to use one of its methods in java. Here is how I call it and it works fine.
Seq<SomeObjectType> variableName = ScalaClass.MethodInTheScalaClass();
I can call this function in java in this form, but since I am calling this method from a compiled package, I can't see what it going on (and therefore I can't change it).
The problem now is that, I don't know how to iterate over the "variableName" in java (since Seq is a scala type).
How can I iterate over variableName or convert it to a Java object (e.g. List)?
Try this:
java.util.List<SomeObjectType> res =
scala.collection.JavaConverters$.MODULE$.seqAsJavaListConverter(variableName).asJava();
You could get converters list in JavaConverters documentation.
You should use JavaConverters$.MODULE$ to get JavaConverters object from Java.

Can I overload JSoup Elements class to getElementsByTag using enum elements rather than strings?

I'm writing something using JSoup, and this is something I've seen elsewhere, many of the methods take strings as arguments.
This sort of things bugs me, I'd much rather use an enum value as an argument. This'd be easy to set up using the HTML.Tag 'enum' and the .toString() method.
Then in my overloaded methods I'd translate the 'enum' to string and feed it into the original method.
So I'd go from calling:
Elements allDivs = bodyElem.getElementsByTag("DIV");
Which is prone to spelling mistakes and not knowning the right tag name, etc to calling:
Elements allDivs = bodyElem.getElementsByTag(HTML.Tag.DIV))
But I can't figure how to overload getElementsByTag to take a HTML.Tag argument.
I've tried this:
Element bodyElem = doc.body(){
Elements getElementsByTag(HTML.Tag tag){
return getElementsByTag(tag.toString());
}
};
But that doesn't work. Specifying this.getElementsByTag refers to the holding class (e.g. HTMLReader, which is one I wrote), and super.getElementsByTag refers to Object.
I'm worried that I just can't do this as Element might be final, like string in this question.
So how should I go about doing this?
JSoup's Element type is not final which means you can extend it, it looks like you are trying to extend it with an anonymous inner class, however you cannot use inner classes to extend an existing object (doc.body() returns an already instantiated Element, you can't modify it).
Your options all depend on what approach you want to take and what seems to have the best cost/complexity to benefit ratio.
1.) Extend the Element class directly and cast the result of doc.body() to your new type that contains your overloaded getElementsByTag method.
2.) Just remember to call the toString() method on your enum type every time you are passing it into the existing getElementsByTag method, it's more verbose but it's either that or cast every Element to something else.
Java eschews some tools from other languages like C#'s extension methods (which would let you do exactly what you want here) for readability and maintainability, unfortunately that sometimes leads to the edge case like this where not having them may make code a little ugly.

Finding an item in an ArrayList in Java?

In C#, finding an item in an ArrayList that have a certain property, it's quite easy:
mSelectedBoard = mBoardConnections.FirstOrDefault(bcd => bcd.Id == id);
This is the easiest I've found to do the same in Java (wish I could afford MonoTouch for android):
for ( BoardConnectionData bcd : mBoardConnections ) {
if (bcd.getID() == id) {
mSelectedBoard = bcd;
break;
}
}
Am I missing an easier way to do this?
Thanks!
Define a meaningful equals and use Collection.contains.
There are a number of utility libraries that contain implementations using various "am I it?" implementations. (Guava, Commons Collections, etc.)
Another option is to create a typed collection containing utility methods finding elements by arbitrary criteria.
In any case, the code snippet shown shouldn't live in the mainline code, it should be abstracted into its own method, regardless of where it ends up living.
Since there are no closures in Java, there's no really easier way to do it. Of course, you can use Guava, but IMHO it offers only a bit of conciseness for a lot of complexity (for your example, at last, because Guava is quite cool otherwise)
Assuming BoardConnectionData class correctly overrides the equals method based on the ID, the following should tell you if the object is in the list or not:
mBoardConnections.contains(object);
If you inherit from Comparable to test for the id member and use a SortedSet:
BoardConnectionData brd =
sortedSet.tailSet(new BoardConnectionData(searchedId)).first();
It is not more efficient complexity-wise, but it is shorter code. :)
To pile on to Dave Newton's answer. The Collection is an ArrayList, so with an appropriate equals (plus hashCode) implementation on BoardConnectionData, the indexOf method would allow the expression
selectedBoard = boardConnections.getAt(boardConnections.indexOf(new BoardConnectionData(id)))
Of course, it's likely preferable to construct a probe object rather than creating a full-blown instance from only the id.
You really should ask your self if ArrayList is the right data structure. Given similar task, I would choose a Map. Both C# and Java will need O(N) to search in an array. Using a map is O(1). If this is something you need to often then I would suggest the right structure.
Really the only difference between the C# and Java version is that one is shorter and uses closure. As many other people have suggested, you can do the same thing with some existing libraries. No one actually showed any code though. With Guava, you can do:
Iterables.find(new Predicate<Data>(){
public boolean apply(Data d){
return d.id == someId;
)}, list);
Or if you want a default value you can use .find(predicate, list, defaultValue).
If you need to match a single property, and multiple items in the list can have identical values for that property, then you need to loop thru like you are doing. Java has a Collections utility class with a bunch of static methods; it might make sense for you to define your own collections utility methods to handle cases like this.
In general though, if you wan't to find an element, just use indexOf and be sure to implement equals properly.
In Java 8 you can do like this:
mSelectedBoard = mBoardConnections
.stream().filter(bcd -> bcd.Id == id).findFirst().orElse(null);

Java equivalent of python's getattr?

I'm converting some python code to java, and have a situation where I need to call methods of an object but don't know which methods until runtime. In python I resolve this by using getattr on my object and passing it a string that is the name of my method. How would you do something similar in Java?
Class.getField is your friend. It probably won't be very straightforward though since Python is dynamically typed and Java is statically typed (unless you know the types of your fields in advance.)
EDIT: How to translate these examples. http://effbot.org/zone/python-getattr.htm
Attribute Lookup
Python
//normal
value = obj.attribute
//runtime
value = getattr(obj, "attribute")
Java
//normal
value = obj.attribute;
//runtime
value = obj.getClass().getField("attribute").get(obj);
Method Call
Python
//normal
result = obj.method(args)
//runtime
func = getattr(obj, "method")
result = func(args)
Java
//normal
result = obj.method(args);
//runtime
Method func = obj.getClass().getMethod("method", Object[].class);
result = func.invoke(obj, args);
In the simpler cases, you need to know whether you have a field or a method. esp as they can have the same name. Additionally methods can be overloaded, so you need to know which method signature you want.
If you don't care which method or field you get, you can implement this as a helper method fairly easily.
You can start here to learn about Java Reflection.
You can use java reflection but there is no exact equivalent of getattr.
In Java you do this with the Reflection API (and it's usually pretty cumbersome).
MethodUtils in Apache Commons BeanUtils project may make it a bit easier to work with, though it's a pretty hefty dependency for something simple like this.
You should use the Reflection API. Since the pure API is a bit ... unapproachable, you should have a look at helpers like commons beanutils or reflections.
The easiest way to handle this is to create a Map object in Java class & keep adding the name value pairs & retrieve it accordingly though it might not support different types that setAttr supports.

Categories