I'm new to java lambda expression so i don't know exactly if what i'm asking is possible. If not possible please suggest a better way if any.
I have an class Object such as:
class Loan {
private String customerId;
private Integer tenure;
private Double amount;
...
}
I need to convert this object into a list of string. The way I'm doing it right now is:
List<String> loanAsList = getListFromLoan(loan);
public List<String> getListFromLoan(Loan loan) {
List<String> loanAsList = new ArrayList<>();
loanAsList.add(loan.getCustomerId());
loanAsList.add(Integer.toString(loan.getTenure());
loanAsList.add(Double.toString(loan.getAmount());
}
Can this be done using a lambda expression?
Loan has many more fields I have only shown a few. I want an expression in which no matter the number of field I could get a List.
A lambda function is just a function. Could you do what you need with a regular method?
If you want to achieve what you say (a method that, no matter how many attributes your class has, adds them all to a list) you'll need to either do it manually and update it every time you add/remove an attribute or use reflection
Something like this:
Loan loan = ...
List<String> loanAsList = new ArrayList<>();
for (Field f : loan.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(loan);
loanAsList.add(value.toString());
}
Object someObject = getItSomehow();
for (Field field : someObject.getClass().getDeclaredFields()) {
field.setAccessible(true); // You might want to set modifier to public first.
Object value = field.get(someObject);
if (value != null) {
System.out.println(field.getName() + "=" + value);
}
}
Lambda Expressions don't do magic in Java 8(well they do but not what you are expecting if I understood you right).
Look at lambda expression as an alternate to anonymous classes, with the advantage that you don't need to wrap it in a class for it implement a function(method in pre java 8 terms). Look up "Behaviour Parameterisation" for a better understanding.
Saying that you can use "Function" functional interface provided by jdk. Represents a function that accepts one argument and produces a result. So you can write a method
public List<String> getListOfAttributes(Loan loan, Function<Loan, List<String>> myFunction) {
return myFunction.apply(loan);
}
and then call this method
getListOfAttributes(loan, (loan) -> {
List<String> loanAsList = new ArrayList();
loanAsList.add(loan.getCustomerId());
loanAsList.add(Integer.toString(loan.getTenure());
loanAsList.add(Double.toString(loan.getAmount());
return loanAsList;
}
so because of "behaviour parameterisation" you can pass in different functionalities to get the different List.
Related
Say I want to convert the below implementation in Java to C#, so that I don't have to cast the returned value at runtime, where the casting should already be handled in the get method.
why not create setters and getters, if you ask? simply because I plan to have 50-100+ attributes and I don't want to create setters and getters for every attributes.
[c#] - what i want to end up doing in c#
string name = playerA.getAttribute(Attribute.NAME);
int age = playerA.getAttribute(Attribute.AGE);
Currently I can't unless I cast the returned value to the correct type. But can I do that casting in side the get method before returning?
[Java] - anyhow, this is the current java implementation that works without casting
//setting attributes
playerA.setAttribute(Attribute.NAME, "Tom");
entityB.setAttribute(Attribute.AGE, 4);
...
//getting the attribute without casting
string name = playerA.getAttribute(PlayerAttribute.NAME);
int age = playerB.getAttribute(PlayerAttribute.AGE);
The method inside a Player/Entity is setup like this to get attributes
[Java]
public <E> E getAttribute(Attribute attr){
//atrributeRepository is EnumMap<Attribute, Object>
//how I will get my attribute value type at runtime
Object result = attributeRepositoryMap.get(attr);
//the enumMap will only ever hold these three type for this example
if(result instanceof Boolean){ return (E) (Boolean) result; }
if(result instanceof String){ return (E) (String) result; }
if(result instanceof Integer){ return (E) (Integer) result; }
return null;
//say all checks are in place and null will never be reach
}
The closest I was able to get in c# is this.
[c#] - though I can deal with it, i would like to prevent casting
string name = (string) getAttribute<string>(Attribute.NAME);
int age = (int) getAttribute<int>(Attribute.AGE);
the method
public T getAttribute<T>(Attribute attribute){
{
Object result = attributeRepositoryDictionary[attribute];
return (T)result;
}
is this as closest as I can get with c#, where casting is needed for getting attributes?
I'm not sure I really like it as an idea - but you could do this by making Attribute generic:
public static class Attributes
{
public static Attribute<int> Age = new Attribute<int>("age");
public static Attribute<string> Name = new Attribute<string>("name");
}
public class Attribute<T>
{
public string Key { get; }
public Attribute(string key)
{
Key = key;
}
...
}
Then you can implement your method as:
public T GetAttribute<T>(Attribute<T> attribute)
{
// attributeDictionary would be a Dictionary<string, object>
return (T) attributeDictionary[attribute.Key];
}
At that point, type inference will be your friend, so you can just write:
int a = player1.GetAttribute(Attributes.Age);
and it'll be equivalent to:
int a = player1.GetAttribute<int>(Attributes.Age);
I was able to find an alternative solution along with #Jon Skeet, which this was more of what I was looking for (not sure if it is an ideal design though). Anyhow, little did I know there was a keyword called "dynamic" in cSharp.
It allowed my method getAttribute() to return any type at runtime, The only requirement is that you must know the return type.
So I do not recommend using this approach if you plan to work with many return types that are in the 5+. That's why I would recommend using something like an enum to give clues on what type will be returned.
In my case, I will only deal with the basic common return types (int, string, float, bool), so its rather easy to know what type will be returned base on the attribute that is called.
class Entity
{
Dictionary<Attribute, Object> attributeRepositoryEnumMap;
...
public dynamic getAttribute(Attribute attribute){
Object result = attributeRepositoryEnumMap[attribute];
return result;
}
}
now I can get return attributes like in the example below without casting
class MyApp
{
Entity e = new Entity();
e.setAttribute(Attribute.NAME, "Bob");
e.setAttribute(Attribute.AGE, 55);
e.setAttribute(Attrbute.HEIGHT, 5.5f);
string name = e.getAttribute(Attribute.NAME);
int age = e.getAttribute(Attribute.AGE);
float height = e.setAttribute(Attribute.HEIGHT);
}
Not sure how this will all work out for me, but a part of this attempt was to also find an easier work around saving and hydrating my json objects without creating tons of setters and getters.
I would like to write a function that would enable me to do the following
inputs: variable number of objects of any type
output: a string that would be NameObj1=ValueObj1, ..., NameObjN=ValueObjN
All objects I would pass to the function would have a toString() method.
Example:
double x=1.1; int y=2; ClassA a
theFunction(x,y,a)
=> this would output "x=1.1, y=1, a=[whatever a.toString() output]"
Is that possible ?
here's something close:
you can write a var-arg function like so:
public static String describeArguments (Object... arguments) {
StringBuilder output = new StringBuilder();
int counter = 1;
for (Object argument : arguments) {
output.append("object #").append(counter++).append(": ").append(argument.toString());
}
return output.toString();
}
strictly speaking method arguments dont have names. you could retrieve the argument parameter name using reflection if the symbol tables werent stripped out #compile time, but its brutish and ugly.
There's no way of getting what you wrote to be the "name" of a variable, because the only way of referencing it, is by itself, and by value is not possible as well.
As mentioned in other answers and comments there is no "name of an object". But if the objects you are interested in are all fields of one class, you could write a function that uses reflection to access that objects fields and prints their names.
Take a look at the reflection tutorial. There is also an example that is very close to what you might have in mind.
You can create a map like
Map<String,Object> map= new HashMap<String,Object>();
map.put("x", 1.1);
map.put("y",2);
map.put("a", MyClass.class);
And call theFunction(map), where theFunction is:
public void theFunction(HashMap<String,Object> list) {
StringBuilder sb = new StringBuilder();
for(String key:list.keySet()) {
try {
Object currentObject = list.get(key);
sb.append(key+"="+currentObject.getClass().getMethod("toString").invoke(currentObject)+" ");
}
catch(Exception e){}
}
System.out.println(sb.toString());
}
I am wondering if there isn't a better way to convert whole Lists or Collections as the way I show in the following code example:
public static List<String> getAllNames(List<Account> allAccounts) {
List<String> names = new ArrayList<String>(allAccounts.size());
for (Account account : allAccounts) {
names.add(account.getName());
}
return names;
}
Every time I produce a method like this, I start thinking, isn't there a better way? My first thought would be to create maybe a solution with some generics and reflections, but this seems maybe a bit over sized and maybe a bit to slow when it comes to performance?
Take a look at Google's Guava library
Something like this should do it
final List<String> names = Lists.transform(myObjs, new Function<MyObject, String>() {
public String apply(final MyObject input) {
return input.getName();
}
});
With Guava, there is a more functional approach:
return FluentIterable.from(allAccounts).transform(new Function<Account,String>(){
public String apply(Account account){return account.getName();}
}).toImmutableList()
But that essentially does the same thing, of course.
BTW: the difference between this answer and RNJ's is that in my case the list will be created once, while in the other answer it's a live view. Both versions are valid, but for different scenarios.
I actually have exactly this kind of method in my personal library.
public static <TSource,TTarget> List<TTarget> castList(List<TSource> sourceList)
{
List<TTarget> targetList = new ArrayList<TTarget>(sourceList.size());
for (TSource t : sourceList) {
//This will throw a ClassCastException if the types are not compatible
//Be carefull
targetList.add((TTarget)t);
}
return targetList;
}
Usage is very simple because the compiler infers the type for TTarget.
List<Object> objects = new ArrayList<Object>();
objects.add("One");
objects.add("Two");
List<String> strings = castList(objects);
Regarding the performance:
I think using generics is no problem here. But the need to copy the whole array is another story.
There is no better way. Casting is a difficult and dangerous thing. In your example, your are not able to cast a String to a MyDataType or vice versa, aren't you?
You might create an own List-Implementation with some kind of toStringList()-Method if you need these more often.
There's a simple way but it is not type safe
List<A> a = new ArrayList<A>();
List<B> b = (List)a;
but then you have to override the implementation of toString() method of your class to return the getName() value.
But there's no type checking,
And as mentioned you can of course do instead a loop and call getName on every object
You could try using the Iterables and Function classes from the Guava libraries. You can create a new type of an Iterable using,
Iterable<String> newTypeIterable = Iterables.transform(oldTypeIterable, new Function<MyDataType, String> () {
#Override
public String apply(MyDataType from)
{
return from.getName();
}
});
Turns out you can do this with the Lists class too!
I have this code:
public static final <TypeVO extends BaseVo> List<SelectItem> populateSelectBoxForType(
final Class<TypeVO> voClass, final String fieldName) {
List<SelectItem> listSelectBox = null;
final List<TypeVO> vosList = GenericEjbProxyFactory
.getGenericTopValueObjectProxy(voClass)
.getAllValueObjects(null);
System.out.println("loaded vosList!!!!");
if (vosList != null) {
listSelectBox = new ArrayList<SelectItem>();
for (final TypeVO currVo : vosList) {
listSelectBox.add(new SelectItem(currVo.getInternalId(), currVo.getName()));
}
}
return listSelectBox;
}
As you see here, I'm using currVo.getName because always, currVo has a name property.
I want to be able to use also other fields from this currVo which has type as voClass, but not all currVo classes will contain this field so I have to use reflection to identify these getField method, something like:
for (final TypeVO currVo : vosList) {
for (final Method m : voClass.getMethods()) {
if (m.getName().contains(fieldName)) {
listSelectBox.add(new SelectItem(
currVo.getInternalId(), currVo.m));
}
}
}
What I do not know is HOW I can use that specific method's value when I find it, exactly like currVo.getName (because, of course, currVo.m is wrong)?
Eg: If fieldName is "Age" I want to put in the list: currVo.getAge()... I am simply blocked here...
m.invoke(currVo);
See also:
Method javadoc
Also note the correct way to look for a method as suggested by Nik and Bohemian.
Do I understand it correctly that you want to invoke the method m on your object currVo? Then it's simply
m.invoke(currVo);
Use reflection to get the getFieldName method and invoke it, as follows:
Method method = voClass.getMethod("get" + fieldName); // the getter with no params in the signature
Object value = method.invoke(currVo}); // invoke with no params
listSelectBox.add(new SelectItem(currVo.getInternalId(), value));
Note: This assumes that fieldName is leading uppercase, eg "Value", not "value", so prepending it with "get" gives the exact method name, eg "getValue"
You should use the invoke method from the Method class.
m.invoke(currVo, (Object[]) null);
(Assuming the method takes no parameter.)
This will work for JDK versions 1.4 and later, since they state:
If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null
The one-parameter version of that call will not work on older JVMs.
I am not sure if i got ur question right, but what i feel u are asking wud be answered by following code:
// Class is whatever is the type u r using
Method mthd = Class.getMethod("get" + fieldName); //in case method don't have any parameters.
listSelectBox.add(mthd.invoke(currVo));
otherwise ignore.
My problem is this; I have to order a table of data. Each row of the table is an object (lets call it TableObject) stored in a List. Each column of data is a property of the class (usually a String).
I have to do the typical ordering of data when the user clicks on any column. So I thought about changing the List to a TreeSet and implementing Comparator in my TableObject.
The problem comes when I try to reorder the TreeSet. The compare is fairly easy at first (cheeking for exceptions in parseInt have been omitted):
public int compare(TableObject to1, TableObject to2){
TableObject t1 = to1;
TableObject t2 = to2;
int result = 1;
if(Integer.parseInt(t1.getId()) == Integer.parseInt(t2.getId())){result=0;}
if(Integer.parseInt(t1.getId()) < Integer.parseInt(t2.getId())){result=-1;}
return result;
}
But when I have to reorder by the text of the data or by other dozens of data that the TableObject has I have a problem.
I do not want to create dozens of compare functions, each for one. I prefer not to use a switch (or a chain of ifs) to decide how to compare the object.
Is there any way to do this in some way (like Reflexive), that doesn't imply that I will write like hundreds of lines of nearly the same code?
Thanks for all!
Bean Comparator should work.
Using reflection the BeanComparator that will allow you to sort on any property that has a zero parameter method that returns the value of the property.
So basically you can sort on any property that has a "getter" method.
What you could do is make the comparator take a String representing the name of the parameter to sort by in its constructor.
Then you could use reflection to sort by the given parameter.
The following code is very dirty. But I think it illustrates the gist of what you would need to do.
public class FieldComparator<T> implements Comparator<T> {
String fieldName;
public FieldComparator(String fieldName){
this.fieldName = fieldName;
}
#Override
public int compare(T o1, T o2) {
Field toCompare = o1.getClass().getField(fieldName);
Object v1 = toCompare.get(o1);
Object v2 = toCompare.get(o2);
if (v1 instanceof Comparable<?> && v2 instanceof Comparable<?>){
Comparable c1 = (Comparable)v1;
Comparable c2 = (Comparable)v2;
return c1.compareTo(c2);
}else{
throw new Exception("Counld not compare by field");
}
}
}
Yes, you could use the reflection API, to get the content of a field based on it's name.
See Field class and especially the Field.get method.
(I wouldn't recommend it though, as reflection is not designed for this type of task.)