【问题标题】:Converting 2D array into 2D ArrayList that is backed by the original array将 2D 数组转换为由原始数组支持的 2D ArrayList
【发布时间】:2021-06-29 04:38:46
【问题描述】:

我已经浏览了有关如何执行此操作的各种示例,并且已经到了这个阶段。我的数据导入被复制到数组列表中,但我没有看到我认为的数据。

当我使用二维数组时,它可以很好地显示导入的数据,但我希望能够对数据进行更改,因此是数组列表。我需要数据来填充两件事,首先是一个 Java 表,然后我将在导出到电子表格中重用数据。如果您能帮助我将二维数组转换为二维(如果这是我需要的)ArrayList,那就太好了。

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

System.out.println(DataImport.dataImport(file_path).length);
System.out.println(Arrays.deepToString(DataImport.dataImport(file_path)));
for (int i = 0; i < DataImport.dataImport(file_path).length; i++) {
    for (int j = 0; j <= 249; j++) {
        student_data.add(new ArrayList<String>(Collections.singleton(
                DataImport.dataImport(file_path)[i][j])));
        System.out.println(student_data.get(i, j));
    }
}

DataImport.dataImport(filepath) 数组在调用 deepToString 作为检查时显示正确的文件路径和数据。所以我知道数据在那里。我是 Java 新手,并且很快就坚持了下来。我修改了输出以在循环完成时显示计数器和数组列表,现在它包含来自数据导入的数据,但是当我需要的是行和列时,每个单元格都在一个单独的列表中。所以这绝对是我需要帮助的填充数组列表的方式。

【问题讨论】:

  • student_data.get(i,j) 原谅我,但我在java.util.ArrayList 类中找不到方法get(int, int)。我错过了什么?
  • 当我使用二维数组时,它可以很好地显示导入的数据,但我希望能够对数据进行更改您的意思是从二维数组中添加或删除元素吗?大批?您可以使用与java.util.ArrayList 类完全相同的方式来执行此操作。创建一个新数组并从现有数组中复制元素,然后用新数组替换现有数组。看看ArrayList类的源代码,

标签: java arrays arraylist multidimensional-array


【解决方案1】:

我不知道DataImport.dataImport(file_path) 是不是一个非常快的调用,但你不应该重复调用它,即使它是。只调用一次也会提高代码的可读性。

既然您想将二维数组转换为二维列表,那么您当然不想使用Collections.singleton()。相反,您希望在外循环内创建一个列表。

String[][] data = DataImport.dataImport(file_path);
System.out.println(data.length);
System.out.println(Arrays.deepToString(data));

ArrayList<ArrayList<String>> student_data = new ArrayList<>();
for (String[] row : data) {
    ArrayList<String> list = new ArrayList<>();
    for (String value : row) {
        list.add(value);
    }
    student_data.add(list);
}

可以使用Arrays.asList() 辅助方法消除内部循环:

String[][] data = DataImport.dataImport(file_path);
ArrayList<ArrayList<String>> student_data = new ArrayList<>();
for (String[] row : data)
    student_data.add(new ArrayList<>(Arrays.asList(row)));

如果您想使用 Java 8 Streams,您可以这样做:

String[][] data = DataImport.dataImport(file_path);
List<List<String>> student_data = Arrays.stream(data)
        .map(row -> Arrays.stream(row).collect(Collectors.toList()))
        .collect(Collectors.toList()));

【讨论】:

    【解决方案2】:

    所以最后在了解了 Akif Hadziabdic 发布的方法后,我开发了自己的解决方案。我把它贴在下面,以防其他人遇到同样的问题。 使用来自Multi Dimensional ArrayList in Java 的指导,我只需在现有数组列表的第一行迭代中创建一个新数组列表。代码很简单:

    ArrayList<ArrayList<String>> student_data = new ArrayList<ArrayList<String>>();
    
    for (int i = 0; i < DataImport.dataImport(file_path).length; i++) {
        student_data.add(new ArrayList<>());
        for (int j = 0; j <= 249; j++) {
            student_data.get(i).add(DataImport.dataImport(file_path)[i][j]);
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以依次使用以下方法:Arrays.stream,然后Arrays::asList 和Collectors.toUnmodifiableList 将多维数组 转换为同一个支持的列表由原始数组组成并且具有固定大小,因为数组总是具有固定大小。

      String[][] array = {{"str1", "str2"}, {"str3"}, {"str4", "str5", "str6"}};
      
      List<List<String>> list = Arrays
              // returns a sequential stream over the array rows
              .stream(array)
              // returns a fixed-size list backed by the
              // specified array row, disallows null
              // values when the array row is null
              .map(Arrays::asList)
              // so as not to confuse the list itself and
              // its internal lists, i.e. array rows, disallows
              // null values when the array row is null
              .collect(Collectors.toUnmodifiableList());
      
      // changing the data in the list
      list.get(1).set(0, "str33");
      
      // you can't add data to the inner lists and to
      // the list itself, only modify existing data
      // list.get(1).add("str34");
      // list.add(Arrays.asList("str71"));
      // UnsupportedOperationException
      
      // output
      System.out.println(Arrays.deepToString(array));
      System.out.println(list);
      //[[str1, str2], [str33], [str4, str5, str6]]
      //[[str1, str2], [str33], [str4, str5, str6]]
      

      【讨论】:

        【解决方案4】:

        您可以使用Arrays#asList 方法为二维数组的行和数组本身实现一个自定义asList 方法:

        /**
         * Returns a fixed-size list backed by the specified array. Changes made to
         * the array will be visible in the returned list, and changes made to the
         * list will be visible in the array...
         *
         * @param array the 2D array by which the list will be backed
         * @param <T>   the class of the objects in the 2D array
         * @return a list view of the specified array
         * @throws NullPointerException if the specified array is 'null',
         *                              or one of its rows is 'null'
         * @see Arrays#asList(Object[])
         */
        public static <T> List<List<T>> asList(T[][] array) {
            return Arrays.asList(Arrays.stream(array)
                    .map(Arrays::asList).<List<T>>toArray(List[]::new));
        }
        
        // test
        public static void main(String[] args) {
            String[][] array = {{"A", "B"}, {"C", "D", null}};
            List<List<String>> list = asList(array);
        
            System.out.println(Arrays.deepToString(array));
            // [[A, B], [C, D, null]]
            System.out.println(list);
            // [[A, B], [C, D, null]]
        
            list.get(1).set(2, "E");
        
            System.out.println(Arrays.deepToString(array));
            // [[A, B], [C, D, E]]
            System.out.println(list);
            // [[A, B], [C, D, E]]
        }
        

        【讨论】:

          【解决方案5】:

          a) 在循环之前只执行一次 DataImport.dataImport(file_path),无需在循环内一直读取它

          var rawData = DataImport.dataImport(file_path)
          

          b) 第二个 j 循环应该迭代到 rawData[i].lenght

          c) 最重要的。您应该在 i-loop 之前创建外部列表,在 j-loop 之前创建内部列表。并在 j-loop 内部将数据添加到内部列表。在 j-loop 之后 - 将此内部列表添加到外部。

          类似

          var rawData = DataImport.dataImport(file_path)
          var studentList = new List<List<>>
          for (int i = 0; i < rawData.lenght; i++) {
              var innerList = new List<>;
              for (int j = 0; i < rawData[i].lenght; j++) {
                  innerList.add(rawData[i][j])
              }
              studentList.add(innerList);
          }
          

          【讨论】:

          • 1) 许多编译错误。 --- 2) 考虑到使用简单的for 循环,OP 可能还使用不支持var 的旧Java 版本。
          猜你喜欢
          • 2011-01-09
          • 1970-01-01
          • 2013-08-14
          • 2014-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多