繁体   English   中英

Java Generics:转换列表<typea>列出<typeb></typeb></typea>

[英]Java Generics: convert List<TypeA> to List<TypeB>

这是一个基本问题,我猜。 然而,来自 C++ 这并不像我预期的那么容易。 请考虑以下代码:

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;
    }
}

这给了我一个错误:“错误:找不到适合 toBar(InT) 的方法”。

我有很多 collections,需要从List<TypeA1>转换为List<TypeB1>List<TypeA2>转换为List<TypeB2> 为了减少代码,我想在 Java Generic 中提取列表迭代,同时在具体实现中进行元素转换。 任何想法,如何做到这一点? 不幸的是,第三方库是不允许的。

非常感谢。

您的static方法没有通过编译,因为您调用的toBar方法需要一个Foo参数,而不是可以是任何东西的泛型类型参数。

您不需要方法来进行转换。 您可以使用相对较短的Stream管道实现相同的目的:

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

当然,如果必须,您可以将其包装在一个方法中,但您必须传递一个Function告诉该方法如何将第一个List的元素转换为第二个List的元素:

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

你用它来称呼它:

List<Foo> foos = ...
List<Bar> bars = convert(foos,TestClass::toBar);

尽管语法相似,但 C++ 模板和 Java generics 非常不同。

在 C++ 中,模板在使用模板时在编译时实例化。 所以如果我写toBar(listOfFoos) ,编译器就会开始编译toBar(List<Foo>)方法。 此时它知道它需要调用toBar(Foo) 如果我在几行之后编写toBar(listOfBazs) ,它会编译一个附加的toBar(List<Baz>)方法,其中可以调用一个完全不同的方法。

另一方面,在 Java 中,该方法只编译一次。 在编译时,必须明确要调用哪个方法。 在您的情况下,它找不到匹配的方法。

一种选择是将方法作为参数传递:

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

并调用它

result = toBar(listOfFoos, TestClass::toBar);

或者您使用 stream:

result = listOfFoos.stream()
                   .map(TestClass::toBar)
                   .collect(Collectors.toList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM