簡體   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