繁体   English   中英

将二维数组转换为由原始数组支持的二维 ArrayList

[英]Converting 2D array into 2D ArrayList that is backed by the original array

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

当我使用二维数组时,它可以很好地显示导入的数据,但我希望能够对数据进行更改,因此是数组列表。 我需要数据来填充两件事,首先是 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));
    }
}

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

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

由于您希望将 2D 数组转换为 2D 列表,因此您当然不想使用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()));

所以最后,在了解了 Akif Hadziabdic 发布的方法之后,我开发了自己的解决方案。 我把它贴在下面,以防其他人遇到同样的问题。 Using guidance from Multi Dimensional ArrayList in Java I simply had to create a new arraylist within the first row iteration within the existing arraylist. 代码很简单:

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]);
    }
}

You can use the following methods in sequence: Arrays.stream , then Arrays::asList and Collectors.toUnmodifiableList to convert a multidimensional array to the same list that is backed by the original array and has a fixed size , since the array is always of一个固定的大小

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]]

您可以使用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]]
}

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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM