你为什么不能在Java中使用List >

Why can't you have a “List<List<String>>” in Java?

本问题已经有最佳答案,请猛点这里访问。

在Java中,为什么下面的代码行不起作用呢?

1
List<List<String>> myList = new ArrayList<ArrayList<String>>();

如果我把它改成

1
List<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();

起初,我想也许你不能有一个接口列表,但是我可以创建一个List,很好。

思想?


一般类型更迂腐。

List表示List或任何子类型,但只表示List。如果需要子类型,则需要使用

我想你可以用

1
List<List<String>> myList = new ArrayList<List<String>>();

你不能这样做的原因是,你可以使用一个引用来引用一个引用,如果有一个额外的间接级别,你必须小心。

1
2
3
4
// with one level of indirection its simple.
ArrayList alist = new ArrayList();
List list = aList; // all good
list = new LinkedList(); // alist is still good.

使用泛型,你可以有两个间接的层次,这可以给你带来问题,所以他们更学究,以避免这些问题。

1
2
3
4
5
// with two levels of indirection
List<ArrayList> alist = new ArrayList<ArrayList>();
List<List> list = (List) alist; // gives you a warning.
list.add(new LinkedList()); // adding a LinkedList into a list of ArrayList!!
System.out.println(alist.get(0)); // runtime error

印刷品

1
2
Exception in thread"main" java.lang.ClassCastException: java.util.LinkedList
     cannot be cast to java.util.ArrayList


让我们从这个开始:

1
    ArrayList<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();

这将创建一个元素为arraylist的arraylist。

现在假设我们可以把它分配给

1
    List<List<String>> myList2 = myList.

现在,我们应该能够做到:

1
    myList2.add(new LinkedList<String>());

但这意味着我们已经向一个元素应该是数组列表的列表中添加了一个LinkedList。哎哟!!!!

实际上,将myList转让给myList2是不合法的……这就确保了不可能在ArrayList>对象中添加错误类型的List。(不,彼得,这不仅仅是学究式的——)


只有顶级集合才能声明为实现类,而嵌套集合必须保留接口,直到实际创建实例:

1
List<List<String>> rootList = new ArrayList<List<String>>();

然后,当您创建一个要进入的元素时,您使它成为一个实现:

1
2
List<String> nodeList = new ArrayList<String>();
rootList.add(nodeList);


它比较了从左(声明)侧到右(实例化)侧的Type。左边是List,右边是ArrayList。如果抱怨差异。

请将右侧(安装)更新为列表,即

1
   List<List<String>> myList = new ArrayList<List<String>>();

这应该很管用。


如果列表中还包含一个列表,则允许使用list> l1=new list>();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public final class CPanelXMLBuilder extends PanelXMLBuilder {

    public CPanelXMLBuilder(AuthenticatedUser pAuthenticatedUser, Map<String, Object> pSessionMap, Map<String, Object> pRequestMap, String pPanelTemplate) throws Exception {
        super(pAuthenticatedUser, pSessionMap, pRequestMap, pPanelTemplate, null);
    }

    public Map<String, Object> buildXMLDocument(List<List<String>> pDetailsList) {

        if (pDetailsList.size() == 1) {
            List<String> pCustomerDetail = pDetailsList.get(0);
            xmlDocument.getRootElement().getChild("E_SHOW1").setText(pCustomerDetail.get(0));
            xmlDocument.getRootElement().getChild("E_SHOW2").setText(pCustomerDetail.get(1));
            xmlDocument.getRootElement().getChild("E_SHOW3").setText(pCustomerDetail.get(2));
            xmlDocument.getRootElement().getChild("E_SHOW4").setText(pCustomerDetail.get(3));
            xmlDocument.getRootElement().getChild("E_SHOW5").setText(pCustomerDetail.get(4));
            xmlDocument.getRootElement().getChild("ServerTimestamp").setText(pCustomerDetail.get(5).substring(0, 19));
        } else {
            xmlDocument.getRootElement().getChild("AlertType").setText("INFO");
            xmlDocument.getRootElement().getChild("Alert").setText("There is no matching record.");
        }

        requestMap.put(RequestMapKeys.XML_DOCUMENT, xmlDocument);

        return requestMap;
    }

}

我知道这是个老问题,但我只想分享我的想法。

我没有列出清单,我只是列出了一个类型为[]的清单(List listArray = new ArrayList();),我生成了一个单独的类型为(List list = new ArrayList();的清单,然后是.add(list.toArray())的清单。这样,它比列表语法更清晰、更容易阅读,这让人困惑。

例如,在最近的一个项目中,我有一个输入文件,其中每行只有一个"0"表示原始文件中的新行(它是一个加密算法):

1
2
3
4
5
6
7
8
9
10
11
12
String[] input = getInputContents(inFile);
List<String> currentBuffer = new ArrayList<String>();
List<String[]> buffers = new ArrayList<String[]>();

for(String line : input) {
    if(line.equals("0")) {
        buffers.add((String[])currentBuffer.toArray());
        currentBuffer = new ArrayList<String>();
    } else {
        currentBuffer.add(line);
    }
}