I wrote this utility function:
public static <T> List<T> pluck(String fieldName, List list)
throws NoSuchFieldException, IllegalAccessException {
if (list.isEmpty()) {
return new ArrayList<T>();
}
Class c = list.get(0).getClass();
Field f = c.getField(fieldName);
ArrayList<T> result = Lists.newArrayList();
for (Object object : list) {
result.add((T) f.get(object));
}
return result;
}
I copied the idea from underscore.js. The use case is:
ArrayList<Person> people = new ArrayList<Person>;
people.add(new Person("Alice", "Applebee"));
people.add(new Person("Bob", "Bedmington"));
people.add(new Person("Charlie", "Chang"));
List<String> firstNames = pluck("firstName", people);
My problem is that if the caller gets the type wrong, no exception is thrown until the caller tried to get an object from the list. Ideally, I'd like to throw a ClassCastException
from the pluck
method itself. However, I don't see a way to access the type of the list on run time.
Is there some trick I can use to make sure the caller doesn't end up with an invalid list?
Edit: So using the feedback I got, a safe implementation would be:
public static <T,F> List<F> pluck(String fieldName, Class<F> fieldType,
List<T> list, Class<T> listType)
throws NoSuchFieldException, IllegalAccessException {
Field f = listType.getField(fieldName);
ArrayList<F> result = new ArrayList<F>();
for (T element : list) {
result.add(fieldType.cast(f.get(element)));
}
return result;
}
But actually lambdaj seems to do what I wanted, so I guess I'll use that. Thanks mike!
Disclaimer: LambdaJ ( @GoogleCode | @GitHub ) - This project is not maintained anymore since the release of JDK8 (JSR 335, JEP 126).
You can change your signature to as follows:
public static <T, F> List<F> pluck(String fieldName, Class<F> fieldType,
List<T> list, Class<T> listType)
The you have the list type and field type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With