如何在Java中操作一个ArrayList的ArrayList?

3

我在Java中操作一个ArrayList的ArrayList时遇到了问题。我的代码中有这个:

ArrayList<ArrayList<Integer>> L1 = new ArrayList<ArrayList<Integer>>();

问题是,我不知道该如何对此进行操作(添加、删除、遍历等)。我希望创建一个邻接表(用于实现简单的无向图),我的教练建议我应该创建一个ArrayList的ArrayList。我知道可以通过以下方式添加新元素-

L1.add(//Something I want to add);

但是在当前情况下,这会因为明显的原因而引发错误。
6个回答

2
一个 ArrayList 里面包含了一个 ArrayList,可以将外部的对象看成是一个 ArrayList 就可以了。
ArrayList<ArrayList<Integer>> list2d = new ArrayList<ArrayList<Integer>>();
// add an element to the list
list2d.add(new ArrayList<Integer>());
// retrieve a list 
ArrayList<Integer> list1d = list2d.get(0);
// add an integer
list2d.get(0).add(123);

顺便说一下,邻接表只是一组边的列表,不需要为每个顶点存储它们,特别是如果图是无向的。 一个Edge列表就足够了:
class Edge {
  Vertex v1, v2;
}

ArrayList<Edge> adjacencyList;

如果您想按顶点存储它们,则可以通过将边封装在顶点类本身中来避免使用列表的列表,但这将需要两倍的边:

class Vertex {
  int value;
  ArrayList<Vertex> adjacency;
}

但哪种方法最好取决于您需要在图上执行的操作类型。对于小型图形,没有实际区别。

如果您只需要知道两个顶点是否相连,则可以使用另一种可能的实现:

class Edge {
  public final int v1, v2;

  public boolean equals(Object o) { return o != null && o instanceof Edge && o.hashCode() == hashCode(); }

  public int hashCode() { return v1 ^ v2; } // simple hash code, could be more sophisticated
}

Set<Edge> adjacencyList = new HashSet<Edge>();

2
这可能会引起误解。通过邻接表,也可能指的是某个顶点的相邻顶点(它们的索引)列表,因此L1.get(i)将返回与索引i相邻的所有顶点索引的列表。 - kenor
每个顶点边缘列表的进展正在以O(n(v))时间获取顶点v的所有邻居n,其中n(v)是v的邻居数。如果仅存储边缘,则需要O(e)时间,其中e是图中的边数。在某些应用程序中,差异可能是关键。 - kenor
@kenor:在那种差异至关重要的情况下,您根本不会使用ArrayList,无论如何,您都会在顶点内使用集合作为邻接列表。如果性能至关重要,则无需进行O(n)查找,而可以进行O(1)查找。 - Jack
当然,那更多是一种假设性的注释,因为出于某种原因,提问者被指示使用列表的列表。 - kenor

1
尝试使用代码L1.get(i).add(whatever);,当然首先要检查是否存在L1.get(i),否则先将该内部列表添加进去。

类似于这样:

List<List<Integer>> L1 = new ArrayList<List<Integer>>(); //better use interfaces

List<Integer> first = null;
if( L1.size() > 0) {
 first = L1.get(0); //first element
}
else {
  first = new ArrayList<Integer>();
  L1.add(first);      
}

first.add(4711); //or whatever you like to add

1
L1.add(new ArrayList<Integer>());

将在第一个列表中创建一个新列表。然后你可以

L1.get(0).add(5)

抱歉,没有集成开发环境(IDE):X - kenor

1
List<List<Integer>> L1 = new ArrayList<ArrayList<Integer>>();    
List<Integer> list1 = new ArrayList<Integer>();     
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);

//将列表添加到列表中
L1.add(list1); 

迭代列表的列表
for( List<Integer> list: L1 ){
      for(Integer i:list){
          System.out.println(i);
      }
}

除非L1被定义为“List<List<Integer>>”,否则“L1.add(list1);”将无法工作。 - Thomas

1
您只能向 L1 添加 ArrayList 类型的对象。因此,您可以这样做:
ArrayList<ArrayList<Integer>> firstList = new ArrayList<ArrayList<Integer>>();

ArrayList<Integer> secondList = new ArrayList<Integer>();
secondList.add(0);

firstList.add(secondList);

1
要向外部数组添加新元素:
ArrayList<Integer> inner = new ArrayList<Integer>();
L1.add(inner);

然后将元素添加到内部数组中:
   int exampleInt = 10;
   ArrayList<Integer> inner = L1.get(0);
   inner.add(exampleInt);

遍历所有数组中的所有元素:
   for (ArrayList<Integer> inner : L1)
   {
      for (Integer element : inner)
      {
         System.out.println(element);
      }
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接