【问题标题】:How to read a list of ArrayLists from file?如何从文件中读取 ArrayLists 列表?
【发布时间】:2018-11-09 19:48:25
【问题描述】:

我正在尝试读取包含图形邻接列表的文件。该文件如下所示:

1 2 3 5
2 4
3 1 5
4 
5 2 4

每一行都是一个链表,其长度与其他行不同。到目前为止,我尝试过这个:

private static List<ArrayList<String>> adj;

ArrayList<String> rows = new ArrayList<String>();

int i = 0;
try {
    Scanner input = new Scanner(new BufferedReader(new FileReader(fileName)));
    //BufferedReader input = new BufferedReader(new FileReader(fileName));

    String line;
    while (input.hasNextLine()){
        i++;
        String[] cols = input.nextLine().trim().split(" ");
        for (String c : cols){
            rows.add(c);
        }
        adj.add(rows);
    }

    //print the matrix
    for (List<String> list : adj) {
        for (String str : list) {
            System.out.print(str + " ");
        }
        System.out.println();
    }
}
catch (IOException e){
    System.out.println("Error reading input file!");
}

但它不起作用,因为当我尝试打印整个矩阵时它显示错误(NullPointerException)。如何正确读取此文件?

【问题讨论】:

  • 你需要在adj.add(rows);后面加上rows = new ArrayList&lt;String&gt;();
  • @Ivan 我试过了。但没有任何变化。仍然无法打印整个矩阵。
  • 那么请添加您用于打印的代码。还有异常堆栈跟踪。
  • 问题是你需要初始化“adj”。
  • 正如@paulsm4 所说,将private static List&lt;ArrayList&lt;String&gt;&gt; adj; 替换为private static List&lt;ArrayList&lt;String&gt;&gt; adj = new ArrayList&lt;&gt;();

标签: java list arraylist


【解决方案1】:

已编辑 我复制了您的代码,对列表进行了初始化,添加了 try/catch 并添加了打印代码,这一切正常:

List<ArrayList<String>> adj = new ArrayList<>();

int i = 0;

Scanner input = null;
try {
    input = new Scanner(new BufferedReader(new FileReader(fileName)));
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

String line;
while (input.hasNextLine()) {
    ArrayList<String> rows = new ArrayList<String>();
    i++;
    String[] cols = input.nextLine().trim().split(" ");
    for (String c : cols) {
        rows.add(c);
    }
    adj.add(rows);
}

for (ArrayList<String> list : adj) {
    for (String s : list) {
        System.out.print(s + " ");
    }
    System.out.println();
}

【讨论】:

    【解决方案2】:

    为此,您确实应该使用“新”Java NIO(Java 7 中引入)中的方法以及流(Java 8 中引入):

    public void readLinesExample(String fileName) throws IOException {
      List<List<String>> adj = Files.readAllLines(Paths.get(fileName)).stream()
          .map(row -> row.split(" "))
          .map(Arrays::asList)
          .collect(toList());
    
      System.out.println(adj.stream().flatMap(Collection::stream).collect(joining(" ")));
    }
    

    这几行代码完成了所有工作,封装在 main() 方法中。

    这很简单:

    • 首先读取所有行,返回一个列表。从文件的行创建一个流。此调用会引发 IOException,因此如果您确实想通过打印到标准输出来处理异常,您可能需要将其包装在一个示例中。
    • 第二行将每一行拆分为一个数组。
    • 第三行,map(Arrays::asList) 从每个数组中创建一个List
    • 最终将列表收集到列表列表中。

    打印部分同样简单。它流过列表列表,并使用平面映射将子列表“扁平化”为一个流。然后它将元素连接成一个字符串,用" " 分隔,并打印出来。

    这比您的原始代码更不容易出错,您几乎不会出错。当然,它在一些细微的方面有所不同,例如 toList() 不保证你会得到 ArrayList,但这并不重要。

    【讨论】:

      【解决方案3】:

      在使用 Java 8 的另一种方法中,您可以简化代码并编写类似这样的内容来读取包含图形邻接列表或任何类似数据的文件。

      public static void printGraph() throws Exception {
          List<String> numberList = Files.readAllLines(Paths.get("graph.txt")); // reads all lines in one shot into a List<String>
      
          List<List<Integer>> listOfIntegerList = new ArrayList<List<Integer>>();
      
          for (String s : numberList) { // for each line containing numbers, stores them into a List<Integer>
              listOfIntegerList.add(Arrays.stream(s.split("\\s+")).map(Integer::parseInt).collect(Collectors.toList()));
          }
      
          System.out.println(listOfIntegerList);
      }
      

      这会根据文件中存在的数据提供以下输出,

      [[1, 2, 3, 5], [2, 4], [3, 1, 5], [4], [5, 2, 4]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-18
        • 2010-09-26
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 2012-05-05
        • 2012-11-12
        相关资源
        最近更新 更多