创建一个setter来提供一个java List Implementation类

时间:2016-10-12 10:02:39

标签: java generics java-7 type-conversion java-5

我正在编写一个基于此界面的小型转换框架:

public interface Converter <From,To> {
    public To convert(final From from);
}

这样我就可以编写自定义类型转换器,例如

public class BigDecimal2Double implements Converter<BigDecimal, Double> {

    @Override
    public Double convert(final BigDecimal value) {
        return value != null ? value.doubleValue() : null;
    }
}

以下类旨在扩展转换器的功能,以处理数据列表。

public abstract class ListConverter<From,To> implements Converter<From,To> {

    public List<To> convertList(List<From> fromList){

        if (fromList == null) {return null;}
        List<To> toList = new ArrayList<>(); // DEFAULT IMPLEMENTATION

        for(From from: fromList ){
            toList.add(this.convert(from));
        }

        return toList;
    }

    public static <From,To> ListConverter<From, To> extend(final Converter<From, To> converter){
        return new ListConverter<From, To>() {

            @Override
            public To convert(From from) {
                return converter.convert(from);
            }
        };
    }
}

因此我可以编写客户端代码,例如:

ListConverter<BigDecimal,Double> lcb2d = ListConverter.extend(new BigDecimal2Double());
List<BigDecimal> bdList = retrieveSomeBigDecList();
List<Double> convertedList = lcb2d.convertList(bdList);

如您所见,这只能为转换后的列表提供默认的ArrayList实现。

我想添加从客户端代码提供不同List实现的功能,例如:

ListConverter<BigDecimal,Double> lcb2d = ListConverter.extend(new BigDecimal2Double());
List<BigDecimal> bdList = retrieveSomeBigDecList();
lcbd.setToListImplementation(LinkedList.class); // How to define such a method?
List<Double> convertedList = lcb2d.convertList(bdList); // would be a LinkedList

我怎么能做到这一点? ListConverter类中的以下代码无法编译:

private Class<? extends List<To>> toListImplementation = ArrayList.class;
public void setToListImplementation(Class<? extends List<To>> listImpl){
    toListImplementation = listImpl;
}

另外,我应该如何使用toListImpl私有字段替换此行?

//... OLD
List<To> toList = new ArrayList<>(); // DEFAULT IMPLEMENTATION
//... NEW 
List<To> toList = toListImplementation.newInstance(); // WOULD WORK???

编辑:Java 8非常酷,我知道有很棒的功能。 我仍然在java 7上工作,我想完成java 5的合规性。

2 个答案:

答案 0 :(得分:2)

为类ListConverter的用户提供一种方法,以提供工厂方法来创建所需的特定类型的List。例如:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public abstract class ListConverter<From, To> implements Converter<From, To> {

    private final Supplier<List<To>> listFactory;

    public ListConverter(Supplier<List<To>> listFactory) {
        this.listFactory = listFactory;
    }

    public List<To> convertList(List<From> fromList) {
        if (fromList == null) {
            return null;
        }

        List<To> toList = listFactory.get();
        for (From from : fromList) {
            toList.add(this.convert(from));
        }

        return toList;
    }

    public static <From, To> ListConverter<From, To> extend(Converter<From, To> converter, Supplier<List<To>> listFactory) {
        return new ListConverter<From, To>(listFactory) {

            @Override
            public To convert(From from) {
                return converter.convert(from);
            }
        };
    }

    public static <From, To> ListConverter<From, To> extend(Converter<From, To> converter) {
        return extend(converter, ArrayList::new);
    }
}

如果您想要LinkedList,那么您可以这样做:

ListConverter<BigDecimal,Double> lcb2d =
        ListConverter.extend(new BigDecimal2Double(), LinkedList::new);

编辑 - 对于Java 5-7,您可以创建ListFactory界面:

import java.util.List;

public interface ListFactory<T> {
    List<T> newList();
}

然后使用它,并使用匿名内部类而不是Java 8方法引用:

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

public abstract class ListConverter<From, To> implements Converter<From, To> {

    private final ListFactory<To> listFactory;

    public ListConverter(ListFactory<To> listFactory) {
        this.listFactory = listFactory;
    }

    public List<To> convertList(List<From> fromList) {
        if (fromList == null) {
            return null;
        }

        List<To> toList = listFactory.newList();
        for (From from : fromList) {
            toList.add(this.convert(from));
        }

        return toList;
    }

    public static <From, To> ListConverter<From, To> extend(Converter<From, To> converter, ListFactory<To> listFactory) {
        return new ListConverter<From, To>(listFactory) {
            @Override
            public To convert(From from) {
                return converter.convert(from);
            }
        };
    }

    public static <From, To> ListConverter<From, To> extend(Converter<From, To> converter) {
        return extend(converter, new ListFactory<To>() {
            @Override
            public List<To> newList() {
                return new ArrayList<To>();
            }
        });
    }
}

答案 1 :(得分:0)

同时,问题被标记为。但如果不是,你可以添加一个版本,如

SELECT [SequenceID]
  ,[AppointmentDate]
FROM dbo].[AmsAppointment]

where AppointmentDate >= Convert(datetime, '2017-01-01' ) and AppointmentDate <= Convert(datetime, '2016-10-01' )

这个得到public abstract class ListConverter<From,To> implements Converter<From,To> { public List<To> convertList(List<From> fromList){ … // as before } public List<To> convertList(List<From> fromList, Supplier<List<To>> supplier){ if (fromList == null) {return null;} List<To> toList = supplier.get(); for(From from: fromList ){ toList.add(this.convert(from)); } return toList; } public static <From,To> ListConverter<From, To> extend(final Converter<From, To> converter){ return (From from) -> converter.convert(from); } } ,根据请求给出一个ArrayList。所以你可以用

来调用它
Supplier

以获取LinkedList而不是ArrayList。

顺便说一句,如果您已经习惯了Streams API,则不需要此ListConverter。您可以点击列表并执行

convertList(myList, LinkedList::new);

或根据需要

list.stream().map(converter::convert).collect(Collectors.toList())