Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics: convert List<TypeA> to List<TypeB>

Tags:

java

generics

this is a basic question, i guess. However, coming from C++ this is not as easy as i expected. Please consider the following code:

import java.util.ArrayList;
import java.util.List;

final class TestClass {

    public class Foo {
        int myInt;
        float myFloat;
    }

    public class Bar {
        int myInt;
        float myFloat;
    }

    private static Bar toBar(Foo in) {
        Bar out = new Bar();
        out.myInt = in.myInt;
        out.myFloat = in.myFloat;
        return out;
    }

    public static <InT, OutT> List<OutT> toBar(List<InT> in) {
        List<OutT> out = new ArrayList<>(in.size());
        for (InT inElement: in) {
            out.add(toBar(inElement));
        }
        return out;
    }
}

This gives me an error: " error: no suitable method found for toBar(InT)".

I have a lot of collections, that need to be converted from List<TypeA1> to List<TypeB1>, List<TypeA2> to List<TypeB2>. To reduce code, i wanted to extract the list iteration in a Java Generic, while doing the element conversion in a concrete implementation. Any ideas, how to do this? Unfortunately, third-party libs are not allowed.

Thanks a lot.

like image 321
mincequi Avatar asked Feb 08 '26 00:02

mincequi


1 Answers

Your static method doesn't pass compilation because the toBar method you are calling expects a Foo argument, not a generic type parameter that can be anything.

You don't need a method to do the conversion. You can achieve the same with a relatively short Stream pipeline:

List<Foo> foos = ...
List<Bar> bars = foos.stream().map(TestClass::toBar).collect(Collectors.toList());

Of course, if you must, you can wrap this in a method, but you'll have to pass a Function that tells the method how to convert an element of the first List to an element of the second List:

public static <InT, OutT> List<OutT> convert(List<InT> in, Function<InT,OutT> converter) {
    return in.stream().map(converter).collect(Collectors.toList());
}

And you call it with:

List<Foo> foos = ...
List<Bar> bars = convert(foos,TestClass::toBar);
like image 158
Eran Avatar answered Feb 09 '26 13:02

Eran