BlackBishop BlackBishop - 1 month ago 5
Java Question

Java - copy items from one list to another using generics

I am trying to make a generic copy from one list to another for certain objects I know the are compatible each other, F can be an argument of T constructor

public static <F,T> List<T> copyFrom(List<F> from){
List<T> to = new ArrayList<T>();
if (from!=null && !from.isEmpty()){
for (F f : from){
to.add(new T.newInstance(f));
}
}
return to;
}


but I don't know to to create an instance of T

Answer

One solution is to pass something to copyFrom that knows how to make a T from an F. For example:

public static <F, T> List<T> copyFrom(List<F> from, Function<F, T> converter) {
    List<T> to = new ArrayList<T>();
    if (from != null && !from.isEmpty()) {
        for (F f : from) {
            to.add(converter.apply(f));
        }
    }
    return to;
}

This uses Java 8's interface java.util.function.Function. If you're not using Java 8, you can write such an interface yourself, it looks like this:

public interface Function<F, T> {
    T apply(F arg);
}

Using Java 8 streams, you can make this much shorter:

public static <F, T> List<T> copyFrom(List<F> from, Function<F, T> converter) {
    if (from == null) {
        return new ArrayList<>();
    }

    return from.stream().map(converter).collect(Collectors.toList());
}

If you have, for example, a class One and a class Two as concrete types and Two has a constructor that takes a One, you can use a method reference Two::new as the converter argument:

class One { ... }

class Two {
    public Two(One one) {
        // ...
    }
}

List<One> list = ...;
List<Two> = copyFrom(list, Two::new);