zhuguowei
zhuguowei

Reputation: 8487

java how to extract some property from a List of some object and also friendly to refactor

When develop java code, always need extract some property from a list of some object, e.g.

List<Foo> fooList = ...
List<Integer> idList = new ArrayList<>();
for(Foo f : fooList){
    idList.add(f.getId());
}

because in production environment we used java7, so I cannot use java8 stream to implement this. So I write an util code to implement this

public static <T, O> List<T> extract(Collection<O> collection, String propertyName) {
    List<T> result = new ArrayList<>(collection.size());
    for (O o : collection) {
        Object val = getFieldValue(propertyName, o);
        result.add((T) val);
    }
    return result;
}

then I implement this just like below

List<Integer> idList = extract(fooList,"id");

but it's not friendly to refactor, if I changed the property name,e.g. id --> fooId, it cannot perceive to this change.

So I want to know how to implement this function refactor friendly and also use it easily?

Upvotes: 0

Views: 509

Answers (2)

Wilson
Wilson

Reputation: 11619

I think you can have a look to Guava. Guava has a Function interface and Collections2.transform(Collection<E>, Function<E,E2>) method provides the feature you require. Following is an example:

final Collection<Foo> fooList = ...;
final Collection<Integer> idList =
    Collections2.transform(fooList, new Function<Foo, Integer>(){

        @Override
        public Integer apply(final Foo foo){
            return foo.getId();
        }
    });

Upvotes: 1

Nicolas Filotto
Nicolas Filotto

Reputation: 44995

Even if you don't use Java 8, you can apply the same logic by using a function as next:

public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

public static <T, O> List<T> extract(Collection<O> collection, Function<O, T> mapper) {
    List<T> result = new ArrayList<>(collection.size());
    for (O o : collection) {
        result.add(mapper.apply(o));
    }
    return result;
}

Indeed using a function instead of a String literal is much easier to refactor and much more Object Oriented.

Your method call will then be something like that:

List<Integer> idList = extract(fooList, new Function<Foo, Integer>() {
    @Override
    public Integer apply(final Foo f) {
        return f.getId();
    }
}); 

Upvotes: 3

Related Questions