列表<列表<字符串>&GT;泛型问题</list <string>

时间:2011-10-02 13:40:51

标签: java list generics

我有以下方法:

public static List<List<String>> createObject() {
    List<List<String>> listOfListOfStrings = new LinkedList<List<String>>();
    List<String> listOfStrings = new LinkedList<String>();
    //do some populating on the lists here
    listOfListOfStrings.add(listOfStrings);
    return listOfListOfStrings;
}

现在我希望能够使用ArrayList / Vector / Stack而不是LinkedList (并根据需要做不同的组合。我读了一些有关此问题的泛型的帖子,我发现了使用工厂模式创建最适合 (因为我不想反射,因为使用通用<T extends List<K>, K extends List<String>>将不起作用< / b>。)。所以我想出的解决方案如下:

public class Tester {
public static void main(String[] args){
    checkGenericsOfLists();
}

public static void checkGenericsOfLists(){
    List<List<String>> listOfListOfStrings = createObject(new LinkedListFactory<List<String>>(), new LinkedListFactory<String>());
    print(listOfListOfStrings);
    translate(listOfListOfStrings);
    print(listOfListOfStrings);
}

public static List<List<String>> createObject(ListFactorable mainListFactory, ListFactorable subListsFactory) {
    List<List<String>> listOfListOfStrings = mainListFactory.create();//new LinkedList<List<String>>();
    List<String> listOfStrings = subListsFactory.create();//new LinkedList<String>();
    listOfStrings.add("A");
    listOfListOfStrings.add(listOfStrings);
    return listOfListOfStrings;
}

public static void transform(List<List<String>> listOfListOfStrings){ 
            //do some abuse on the lists here.
}}

此解决方案发出警告:

  

ListFactorable是原始类型。对泛型类型ListFactorable的引用应该参数化

这适用于createObject方法签名。和

  

类型安全:类型List的表达式需要未经检查的转换以符合字符串列表列表&gt;&gt;

这适用于工厂调用create()方法的行。

但如果我使用这个:

public static List<List<String>> createObject(ListFactorable<List<List<String>>, List<String>> mainListFactory, ListFactorable<List<String>, String> subListsFactory) {
    List<List<String>> listOfListOfStrings = mainListFactory.create();//new LinkedList<List<String>>();
    List<String> list = subListsFactory.create();//new LinkedList<String>();
    list.add("A");
    listOfListOfStrings.add(list);
    return listOfListOfStrings;
}

我收到编译错误:

The method createObject(ListFactorable<List<List<String>>,List<String>>, ListFactorable<List<String>,String>) in the type Tester is not applicable for the arguments (LinkedListFactory<List<String>>, LinkedListFactory<String>)

有什么方法可以让编译器不抛出警告或错误,并且在没有createObject方法知道所使用的List实现的情况下(在编译期间)实例化这些列表?!

干杯,

修改: 请原谅我没有发布其他课程(非常愚蠢的我:))。我们走了:

public interface ListFactorable<T extends List<K>, K> {
T create();}

public class LinkedListFactory<K> implements ListFactorable<LinkedList<K>, K> {
public LinkedList<K> create(){
    return new LinkedList<K>();
}}

EDIT2(Eugene承担问题):

public interface EugeneListFactorable<T extends List<?>> {T create();}

public class EugeneLinkedListFactory implements EugeneListFactorable<LinkedList<?>> {
    public LinkedList<?> create(){
        return new LinkedList<List<?>>();
    }
}
public static void checkGenericsOfLists2(){
    List<List<String>> listOfListOfStrings = createObject(new EugeneLinkedListFactory(), new EugeneLinkedListFactory());
    translate(listOfListOfStrings);
}

编译器错误:

    - Type mismatch: cannot convert from LinkedList<?> to List<List<String>>
- Bound mismatch: The generic method createObject(EugeneListFactorable<N>, EugeneListFactorable<M>) of type 
 Tester is not applicable for the arguments (EugeneLinkedListFactory, EugeneLinkedListFactory). The inferred type LinkedList<?> 
 is not a valid substitute for the bounded parameter <N extends List<List<String>>>

请尝试编译并运行我发布的示例和您的解决方案。它是一个测试类,您可以在您的IDE上轻松运行。谢谢!

3 个答案:

答案 0 :(得分:2)

以下内容“在我的机器上运行”,没有任何警告或错误。我不知道的是所有大惊小怪的原因 - 请参阅秒代码块。

public class Tester {

    public static void main(String[] args) {
        checkGenericsOfLists();
    }

    public static void checkGenericsOfLists() {
        List<List<String>> listOfListOfStrings = createObject(
                new LinkedListFactory<List<String>>(),
                new LinkedListFactory<String>());
        transform(listOfListOfStrings);
    }

    public static List<List<String>> createObject(
            ListFactorable<List<List<String>>, List<String>> mainListFactory, 
            ListFactorable<List<String>, String> subListsFactory
    ) 
    {
        List<List<String>> listOfListOfStrings = mainListFactory.create();
        List<String> listOfStrings = subListsFactory.create();
        listOfStrings.add("A");
        listOfListOfStrings.add(listOfStrings);
        return listOfListOfStrings;
    }

    public static void transform(List<List<String>> listOfListOfStrings) {
        // do some abuse on the lists here.
        System.out.println(listOfListOfStrings);
    }

    public interface ListFactorable<T extends List<K>, K> {
        T create();
    }

    static public class LinkedListFactory<K> implements ListFactorable<List<K>, K> {
        public LinkedList<K> create() {
            return new LinkedList<K>();
        }
    }
}

这个解决方案有点清洁,省去了一些泛型噪音。

public class Tester2 {
    public static void main(String[] args) {
        checkGenericsOfLists();
    }

    public static void checkGenericsOfLists() {
        List<List<String>> listOfListOfStrings = createObject(
                new LinkedListFactory<List<String>>(),
                new LinkedListFactory<String>());
        transform(listOfListOfStrings);
    }

    public static List<List<String>> createObject(
            ListFactory<List<String>> mainListFactory, 
            ListFactory<String> subListsFactory
    ) 
    {
        List<List<String>> listOfListOfStrings = mainListFactory.create();
        List<String> listOfStrings = subListsFactory.create();
        listOfStrings.add("A");
        listOfListOfStrings.add(listOfStrings);
        return listOfListOfStrings;
    }

    public static void transform(List<List<String>> listOfListOfStrings) {
        // do some abuse on the lists here.
        System.out.println(listOfListOfStrings);
    }

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

    static public class LinkedListFactory<T> implements ListFactory<T> {
        public List<T> create() {
            return new LinkedList<T>();
        }
    }
}

答案 1 :(得分:1)

这不能完全解决您的问题,但它有助于更​​快地找到解决方案。

当你有任何看起来像这样的事情时X&gt;考虑重构成一个类。我举一个例子。你看起来像是在使用翻译。现在我不确切地知道你的目标是什么,因为你没有说明,但一种常见的方法是:

List<String> english = new LinkedList<String>();
List<String> french = new LinkedList<String>();
List<String> spanish = new LinkedList<String>();

List<List<String>> languages = new LinkedList<List<String>>();
languages.add(english);
languages.add(french);
languages.add(spanish);

for(String word : someWordList) {
    for(List<String> language : languages) {
         // oh snap! I really have no idea what language I'm working in...
         // I could do something silly like make list.get(0) be the language
         // name, but that seems lame
    }
}

更好的是这样的事情:

class Language {
    final String language;
    final Map<String,String> english2current;
    Language(String language, Set<String> words) {
        this.language = language;
        english2current = new HashMap<String,String>();
        Translator t = TranslatorFactory.getTranslator(language);
        for(String word : words) english2current.put(word,t.translate(word));
    }
}

Collection<String> wordSet() {
    return english2current.values();
}

现在没有看到更多的实施,很难确切地看到你做错了什么。但是无论你做什么,看看删除任何嵌套的泛型,而是试图将它们分离成类。这将允许您以面向对象的方式合并行为,并更好地组织您的逻辑,以便您可以专注于它应该做的事情而不是泛型的语义。

答案 2 :(得分:0)

你需要正确的ListFactorable类:

public class ListFactorable<T extends List<?>> {
  public T create() {
    ...
  }
}

然后createObject方法看起来像这样:

public static <N extends List<List<String>>,M extends List<String>> N createObject( //
        ListFactorable<N> mainListFactory, //
        ListFactorable<M> subListsFactory) {
    N listOfListOfStrings = mainListFactory.create();//new LinkedList<List<String>>();
    M listOfStrings = subListsFactory.create();//new LinkedList<String>();
    listOfStrings.add("A");
    listOfListOfStrings.add(listOfStrings);
    return listOfListOfStrings;
}