如何在Java中用整数填充二维ArrayList?

6
我需要创建一个大小未知的二维数组。因此,我决定使用一个二维ArrayList,但问题是我不确定如何初始化这样的数组或存储信息。
例如,假设我有以下数据。
   0 connects 1
   2 connects 3 
   4 connects 5

"等等直到大量随机连接" 然后我想插入 "

"
true(1) into [0][1], 
true(1) into [2][3], 
true(1) into [4][5]. 

数组能否自动更新列/行

感谢任何帮助

8个回答

22

我不确定如何初始化这样的数组或存储信息。

例如这样:

List<List<Integer>> twoDim = new ArrayList<List<Integer>>();

twoDim.add(Arrays.asList(0, 1, 0, 1, 0));
twoDim.add(Arrays.asList(0, 1, 1, 0, 1));
twoDim.add(Arrays.asList(0, 0, 0, 1, 0));

或者如果你喜欢这样:

List<List<Integer>> twoDim = new ArrayList<List<Integer>>() {{
    add(Arrays.asList(0, 1, 0, 1, 0));
    add(Arrays.asList(0, 1, 1, 0, 1));
    add(Arrays.asList(0, 0, 0, 1, 0));
}};
为了插入一行新记录,你可以执行以下操作:
twoDim.add(new ArrayList<Integer>());

要在特定的 row 上追加另一个元素,您可以执行以下操作:

twoDim.get(row).add(someValue);

以下是一个更完整的示例:

import java.util.*;

public class Test {

    public static void main(String[] args) {

        List<List<Integer>> twoDim = new ArrayList<List<Integer>>();

        String[] inputLines = { "0 1 0 1 0", "0 1 1 0 1", "0 0 0 1 0" };

        for (String line : inputLines) {
            List<Integer> row = new ArrayList<Integer>();

            Scanner s = new Scanner(line);
            while (s.hasNextInt())
                row.add(s.nextInt());

            twoDim.add(row);
        }
    }
}

我需要指定一个特定的行和列。如何将数字插入到此ArrayList的[0][1]、[0][2]等位置? - xiao
@eNetik,要设置特定的值,您可以使用toDim.get(x).set(y, value);。但是,这假定您已经构建了空数组。为了使更新有东西可更新,您必须最初以类似于上面代码的方式构建数组(即使您只将所有值设置为零)。 - Edwin Buck
@eNetik,添加了一个更完整的示例。 - aioobe
@Edwin Buck,我不知道数组的大小。这是一个文件读取,我需要根据连接的节点创建邻接矩阵。因此,我需要在一开始就设置正确的数组[0][1] = 1。随着文件继续读取,我需要继续这个过程...我想知道如果我添加项目后,arrayList是否会自动构建其行/列。 - xiao
不,ArrayLists不会“用零填充”或其他类似的方式,如果您尝试在特定索引处输入值。您可以追加,并更新中间的值,但无法“在任意索引处添加值”。 - aioobe
@aioobe +1,去睡觉吧。 - OscarRyz

18
List<List<Integer>> array = new ArrayList<List<Integer>>();
// add row:
array.add( new ArrayList<Integer>() );
// add a column:
array.get( array.size() -1 ).add( 1 );

工作演示:

import java.util.*;
import static java.lang.System.out;
class Load { 
    public static void main( String ... args ) { 

        List<List<Integer>> array = new ArrayList<List<Integer>>();

        Scanner input = new Scanner(System.in);
        out.println("Enter n:");
        int n = input.nextInt();

        out.println("Enter m:");
        int m = input.nextInt();

        out.println("Enter the values:");

        for( int i = 0 ; i < n ; i++ ) { 
            // add row:
            List<Integer> list = new ArrayList<Integer>();
            array.add( list );
            for( int j = 0 ; j < m ; j++ ) { 
                // add a column:
                // array.get( array.size() -1 ).add( 1 ); or
                list.add( input.nextInt() );
            }
        }
        out.println("Result:");
        out.println( array );

    }
}

输出:

C:\>java Load
Enter n:
3
Enter m:
6
Enter the values
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Result:
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17]]

0

对于后续问题的简短回答是:

array.get(i1).put(i2, value);

但是如果ArrayList的大小小于或等于索引,get和put都可能失败。因此,如果您想填入任意值,需要编写必要的扩展方法。然后调用将类似于

putCell(getRow(array, i1), i2, value)

在这里,getRow() 知道如何增加 ArrayList 的 ArrayList,而 putCell() 则知道如何增加 ArrayList。


0

如果您没有提前获取所有数据以利用aioobe的解决方案,您可以使用Google Guava库中的Table。

Table<Integer,Integer,Integer> matrix = new HashBasedTable<Integer,Integer,Integer>();
matrix.put(rowIndex,columnIndex,value);

这种方法的主要缺点是,如果你处理大量数据,它并不是非常快或者内存使用效率高,因为所有内容都是哈希表查找,并且原始类型被Integer封装。


我不认为我被允许使用外部库 :(。我正在处理 .java 文件。 - xiao

0

如果你知道你的数据有3行5列(如你所示的数据示例),你可以按照以下方式进行初始化:

int[][] a = new int[3][5]; 

但是,如果行数发生变化,你可以这样做:
String dataStr = "0,1,0,1,0:0,1,1,0,1:0,0,0,1,0";

String[] rows = dataStr.split(":");

String[] cols = rows[0].split(",");

现在你可以初始化:

int[][] a = new int[rows.length][cols.length];

这将适应不断变化的行和列大小。可能不是最优雅的方法,但它应该能够工作。


0

你的例子看起来像是想要从一对整数映射到布尔值(默认值为false)。如果这是一个稀疏的映射(即真正大多数位置都是false),你可以考虑使用类似 HashSet 的数据结构或者自定义一个包含两个整数并且有合适的 hashCode 和 equals 实现的类。

class IntPair {
   int first;
   int second;
   public boolean equals(Object o) {
      return o instanceof IntPair &&
         ((IntPair)o).first == first &&
         ((IntPair)o).second == second;
   }
   /** optimized for small numbers */
   public int hashCode() {
       return first + second * 44729;
   }
   public String toString() {
     return "(" + first + ", " + second + ")";
   }
}

那么,要表示“0 连接 1”,你应该写成:

set.add(new IntPair(0,1));

这真的取决于您之后想要使用什么操作 - 像HashSet这样的数据结构具有快速查找和更改的功能,并且不会占用太多空间,但是您无法快速地“获取节点1的所有邻居”。如果您需要这样的访问权限,您可能只需要一个类似的数据结构:

class Node {
   int id;
   Set<Node> neighbours;
}

并且另外一个包含这些节点的列表/数组/集合。

“大小未知的数组”这个问题不够具体,无法进行有力回答。


0

由于您只需要在该二维数组中存储布尔值,我会建议最合适的数据结构(既考虑内存消耗又具有有用接口)是 java.util.BitSet,它基本上是一个模拟位数组的类:

因为这是一个二维数组,所以我认为最好的选择是:

List<BitSet> bitArrays = new ArrayList<BitSet>();

在列表中,你不能仅仅说“这是第5个元素”,而不插入前4个元素。但是在BitSet中,你可以简单地使用set()设置任何需要的位,它将自动扩展到所需的大小。

0
  import java.util.*;
    public class ArrayListDS { 
        public static void main( String [] args ) { 

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

           Scanner sc = new Scanner(System.in);

           System.out.println("Enter the number of row: ");
           int n = sc.nextInt();

           for(int i = 0; i < n; i++){

               ArrayList<Integer> col = new ArrayList<Integer>();
               row.add(col);

           System.out.println("Enter the number of column: ");
           int m = sc.nextInt();

               for(int j = 0; j < m; j++){
                    col.add(sc.nextInt()); 
               }
               System.out.println();
           }
           System.out.println(row);
        }
    }

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