簡體   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