Решение с использованием метода Generi c
Определите ваш метод generi c как
public static <T> List<T> convertGeneric(List<List<Object>> dataframe, Function<Object, T> converter)
, т.е. первый аргумент - это ваша коллекция объектов, а в качестве второго аргумента Вы предоставляете функцию преобразования из Object
в целевой класс. Метод возвращает List<T>
. (Обратите внимание на <T>
после static
, который требуется для объявления метода generi c.
Реализация метода может быть
public static <T> List<T> convertGeneric(List<List<Object>> dataframe, Function<Object, T> converter) {
List<T> result = new ArrayList<>();
for (List<Object> objects : dataframe) {
for (Object object : objects) {
T t = converter.apply(object);
result.add(t);
}
}
return result;
}
или другой, использующей потоки:
public static <T> List<T> convertGeneric(List<List<Object>> dataframe, Function<Object, T> converter) {
return dataframe.stream()
.flatMap(Collection::stream) // get the objects from the inner list
.map(converter) // convert object to T
.collect(Collectors.toList()); // put everything in a new list
}
Функция преобразования может быть реализована как лямбда, например,
Function<Object, Foo> fooLambda = object -> {
Foo foo = new Foo();
// logic for mapping obj to foo
return foo;
};
И преобразование List<List<Object>>
в List<Foo>
становится:
List<Foo> fooList = GenericMethodConverter.convertGeneric(dataFrame, fooLambda);
Я думаю, что причина, по которой вы боролись с этой проблемой, заключается в том, что вы пытались сделать все (абстрактное и конкретное) в методе generi c. Вы знали, что метод generi c требует дополнительной информации, что конкретная реализация для использования (в вашей версии путем передачи в качестве второго аргумента целевого типа для преобразования). В приведенном выше решении для метода generi c требуется функция преобразования Function<Object,T>
, то есть функция, которая отображает объект на тип цели T. Метод generi c применяет эту функцию ко всем объектам и помещает результаты в возвращенный список. Конкретная реализация для отображения object
в Foo
предоставляется в виде лямбда-выражения, таким образом преобразуя родовые c T
в Foo
. Другие функции преобразования могут быть добавлены по мере необходимости.
Другой подход
Это решение, использующее объектные ориентации / классы вместо методов stati c:
Определение абстрактного базового класса GenericConverter
, который содержит итерацию для над списком и объявляет абстрактный метод преобразования Object
в целевой тип:
public abstract class GenericConverter<T> {
public List<T> convertGenerically(List<List<Object>> dataFrame) {
List<T> tList = new ArrayList<>();
for (List<Object> objectList : dataFrame) {
for (Object obj : objectList) {
T t = convert(obj);
tList.add(t);
}
}
return tList;
}
protected abstract T convert(Object obj);
}
Добавьте реализацию для каждого целевого класса, например, для преобразования Object
в Foo
:
public class FooConverter extends GenericConverter<Foo> {
@Override
protected Foo convert(Object obj) {
Foo foo = new Foo();
// logic for mapping obj to foo
return foo;
}
}
А затем преобразовать Objects
, вызвав метод реализации класса:
List<Foo> foos = fooConverter.convertGenerically(dataFrame);