2011-08-19 28 views
36

Làm cách nào để điền vào một mảng đa chiều trong Java mà không sử dụng vòng lặp? Tôi đã thử:Arrays.fill với mảng đa chiều trong Java

double[][] arr = new double[20][4]; 
Arrays.fill(arr, 0); 

Điều này dẫn đến java.lang.ArrayStoreException: java.lang.Double

Cảm ơn trước!

+2

nhưng tại sao không sử dụng một vòng lặp? –

+2

@Caroline: Nếu bạn đang cố gắng khởi tạo mảng 2d bằng 0, u không cần làm như vậy vì nó đã được khởi tạo với 0 khi bạn cấp phát mảng và bạn không thể khởi tạo bất kỳ mảng nào mà không sử dụng vòng lặp.Bạn chỉ có thể ẩn lặp lại trong một hàm giống như Arrays.fill. – Emil

+1

Xin chào, các bạn không phóng đại nó ngay bây giờ. Tất cả những gì anh ta muốn là một số phương thức trong Java API để khởi tạo các mảng đa chiều tới một số giá trị mặc định trong một bước duy nhất. Đó là những gì anh muốn nói mà không có một vòng lặp. –

Trả lời

48
double[][] arr = new double[20][4]; 
Arrays.fill(arr[0], 0); 
Arrays.fill(arr[1], 0); 
Arrays.fill(arr[2], 0); 
Arrays.fill(arr[3], 0); 
Arrays.fill(arr[4], 0); 
Arrays.fill(arr[5], 0); 
Arrays.fill(arr[6], 0); 
Arrays.fill(arr[7], 0); 
Arrays.fill(arr[8], 0); 
Arrays.fill(arr[9], 0); 
Arrays.fill(arr[10], 0); 
Arrays.fill(arr[11], 0); 
Arrays.fill(arr[12], 0); 
Arrays.fill(arr[13], 0); 
Arrays.fill(arr[14], 0); 
Arrays.fill(arr[15], 0); 
Arrays.fill(arr[16], 0); 
Arrays.fill(arr[17], 0); 
Arrays.fill(arr[18], 0); 
Arrays.fill(arr[19], 0); 
+3

Xin chào. Tôi chỉ tò mò để biết lý do tại sao bạn đề xuất giải pháp này và không phải là một cổ điển 'cho'. Có động lực không? Cảm ơn! – Maverik

+61

Vì những từ sau trong câu hỏi: "không sử dụng vòng lặp". Giải pháp của tôi là vô lý, nhưng nó trả lời đúng câu hỏi. – trojanfoe

+2

Rất tiếc, đã bỏ lỡ "mà không sử dụng vòng lặp" từ OP: đã xóa bỏ phiếu bầu của tôi. Có lẽ bạn nên có một nhận xét trong câu trả lời của bạn rằng đề nghị không nên được thực hiện quá nghiêm túc. –

69

này là do một double[][] là một mảng của double[] mà bạn không thể gán 0.0 đến (nó sẽ giống như làm double[] vector = 0.0). Trong thực tế, Java không có các mảng đa chiều thực sự.

Vì nó xảy ra, 0.0 là giá trị mặc định cho đôi trong Java, do đó ma trận sẽ thực sự đã được lấp đầy với số không khi bạn nhận được nó từ new. Tuy nhiên, nếu bạn muốn điền nó với, ví dụ: 1.0 bạn có thể thực hiện các thao tác sau:

Tôi không tin rằng API cung cấp một phương pháp để giải quyết vấn đề này mà không cần sử dụng vòng lặp. Tuy nhiên, nó đủ đơn giản để thực hiện nó với một vòng lặp for-each.

double[][] matrix = new double[20][4]; 

// Fill each row with 1.0 
for (double[] row: matrix) 
    Arrays.fill(row, 1.0); 
+0

Điều này cũng đủ 'Arrays.fill (arr, 0d);' hoặc 'Arrays.fill (arr, (double) 0);' –

+2

Tôi nhận được ' Ngoại lệ trong chuỗi "main" java.lang.ArrayStoreException: java.lang.Double' trừ khi tôi lặp lại các hàng. – aioobe

+0

Tại sao bạn không cố gắng hiểu câu trả lời này? Trong java (và C và C++) không có mảng đa chiều !!! Ma trận của bạn là một mảng một chiều đơn giản, trong đó mỗi "trường" lại một mảng mờ. Cuộc gọi của bạn đến Arrays.fill() cố gắng đặt một _int_ (để có một đôi ghi 0.0 và không chỉ đơn giản là 0) vào "ma trận", mà không hoạt động. –

3

làm thế nào tôi có thể điền vào một mảng đa chiều trong Java mà không sử dụng một vòng lặp?

Mảng đa chiều chỉ là mảng mảng và fill(...) không kiểm tra loại mảng và giá trị bạn chuyển vào (trách nhiệm này dựa trên nhà phát triển).

Vì vậy, bạn không thể điền một mảng nhiều chiều hợp lý mà không sử dụng vòng lặp. Hãy chú ý đến thực tế rằng, không giống như các ngôn ngữ như C hoặc C++, các mảng Java là các đối tượng và trong các mảng đa chiều nhưng mức cuối cùng chứa tham chiếu đến các đối tượng khác Array. Tôi không chắc chắn 100% về điều này, nhưng rất có thể chúng được phân phối trong bộ nhớ, do đó bạn không thể chỉ cần điền vào một khối liền kề mà không có vòng lặp, như C/C++ sẽ cho phép bạn làm.

7

OP hỏi làm thế nào để giải quyết vấn đề này mà không có vòng lặp! Đối với một số lý do nó là thời trang những ngày này để tránh vòng. Tại sao điều này? Có thể có một nhận thức rằng việc sử dụng map, reduce, filter và bạn bè cũng như các phương pháp như each ẩn các vòng lặp và cắt giảm phân đoạn chương trình và thật tuyệt. Cũng vậy với các đường dẫn Unix thực sự ngọt ngào. Hoặc mã jQuery. Mọi thứ trông tuyệt vời không có vòng lặp.

Nhưng Java có phương pháp map không? Không thực sự, nhưng chúng ta có thể xác định một với giao diện Function với phương thức eval hoặc exec. Nó không phải là quá khó và sẽ là một bài tập tốt. Nó có thể tốn kém và không được sử dụng trong thực tế.

Cách khác để thực hiện việc này mà không cần lặp lại là sử dụng tính năng đệ quy đuôi. Có, nó là loại ngớ ngẩn và không ai sẽ sử dụng nó trong thực tế, hoặc, nhưng nó cho thấy, có thể, rằng vòng là tốt trong trường hợp này.Tuy nhiên, chỉ cần để hiển thị "thêm một vòng lặp miễn phí ví dụ" và để vui chơi, ở đây là:

import java.util.Arrays; 
public class FillExample { 
    private static void fillRowsWithZeros(double[][] a, int rows, int cols) { 
     if (rows >= 0) { 
      double[] row = new double[cols]; 
      Arrays.fill(row, 0.0); 
      a[rows] = row; 
      fillRowsWithZeros(a, rows - 1, cols); 
     } 
    } 

    public static void main(String[] args) { 
     double[][] arr = new double[20][4]; 
     fillRowsWithZeros(arr, arr.length - 1, arr[0].length); 
     System.out.println(Arrays.deepToString(arr)); 
    } 
} 

Nó không phải là đẹp, nhưng trong câu trả lời cho câu hỏi của OP, không có rõ ràng vòng.

+0

+1, không phải cho giải pháp, nhưng đối với một câu trả lời thực sự tốt – Dragon8

+0

Cảm ơn tất cả các giải pháp của bạn! Lý do tại sao tôi không muốn sử dụng vòng lặp? Tôi đã tìm kiếm một giải pháp đơn giản để tạo ra một ma trận n-by-n của số không như trong MATLAB. – Caroline

+0

Điều này vẫn có thể gây ra một tràn ngăn xếp, như Java không có hỗ trợ đệ quy đuôi, vì vậy vòng chắc chắn> đệ quy. – mc10

1

Là phần mở rộng cho câu trả lời, tôi đã tìm thấy bài đăng này nhưng đang tìm cách lấp đầy mảng 4 chiều. Ví dụ ban đầu chỉ là mảng hai chiều, nhưng câu hỏi cho biết "đa chiều". Tôi không muốn đăng câu hỏi mới cho việc này ...

Bạn có thể sử dụng cùng một phương pháp, nhưng bạn phải lồng ghép chúng để cuối cùng bạn có được một mảng chiều.

fourDArray = new float[10][10][10][1]; 
// Fill each row with null 
for (float[][][] row: fourDArray) 
{ 
    for (float[][] innerRow: row) 
    { 
     for (float[] innerInnerRow: innerRow) 
     { 
     Arrays.fill(innerInnerRow, -1000); 
     } 
    } 
}; 
-5
Arrays.fill(arr, new double[4]); 
+1

Dòng này làm cho mọi hàng tham chiếu đến cùng một khối bộ nhớ, tức là thay đổi arr [1] [5] cũng sẽ thay đổi arr [100] [5]. –

0

Đừng tất cả chúng ta đôi khi muốn có một
<T>void java.util.Arrays.deepFill(T[]…multiDimensional). Sự cố bắt đầu với
Object threeByThree[][] = new Object[3][3];
threeByThree[1] = null;
threeByThree[2][1] = new int[]{42}; hoàn toàn hợp pháp.
(Nếu chỉ Object twoDim[]final[] là hợp pháp và được xác định rõ ...)
(Sử dụng một trong những phương pháp nào từ bên dưới giữ vòng từ mã nguồn gọi.
Nếu bạn nhấn mạnh vào việc sử dụng không có vòng ở tất cả, thay thế các vòng và cuộc gọi để Arrays.fill() (!) sử dụng đệ quy.)

/** Fills matrix {@code m} with {@code value}. 
* @return {@code m}'s dimensionality. 
* @throws java.lang.ArrayStoreException if the component type 
* of a subarray of non-zero length at the bottom level 
* doesn't agree with {@code value}'s type. */ 
public static <T>int deepFill(Object[] m, T value) { 
    Class<?> components; 
    if (null == m || 
     null == (components = m.getClass().getComponentType())) 
     return 0; 
    int dim = 0; 
    do 
     dim++; 
    while (null != (components = components.getComponentType())); 
    filler((Object[][])m, value, dim); 
    return dim; 
} 
/** Fills matrix {@code m} with {@code value}. 
* @throws java.lang.ArrayStoreException if the component type 
* of a subarray of non-zero length at level {@code dimensions} 
* doesn't agree with {@code value}'s type. */ 
public static <T>void fill(Object[] m, T value, int dimensions) { 
    if (null != m) 
     filler(m, value, dimensions); 
} 

static <T>void filler(Object[] m, T value, int toGo) { 
    if (--toGo <= 0) 
     java.util.Arrays.fill(m, value); 
    else 
     for (Object[] subArray : (Object[][])m) 
      if (null != subArray) 
       filler(subArray, value, toGo); 
} 
0
public static Object[] fillArray(Object[] arr,Object item){ 
    Arrays.fill(arr, item); 
    return arr; 
} 
Character[][] maze = new Character[10][10]; 
    fillArray(maze, fillArray(maze[0], '?')); 

    for(int i = 0;i<10;i++){ 
     System.out.println(); 
     for(int j = 0;j<10;j++){ 
      System.out.print(maze[i][j]); 
     } 
    } 

tôi hy vọng điều này làm tốt

0

sử dụng Java 8, bạn có thể khai báo và khởi tạo một mảng hai chiều mà không sử dụng (rõ ràng) Vòng lặp như sau:

int x = 20; // first dimension 
int y = 4; // second dimension 

double[][] a = IntStream.range(0, x) 
         .mapToObj(i -> new double[y]) 
         .toArray(i -> new double[x][]); 

này sẽ khởi tạo mảng với giá trị mặc định (0.0 trong trường hợp double).

Trong trường hợp bạn muốn xác định một cách rõ ràng giá trị điền để được sử dụng, Bạn có thể thêm vào một DoubleStream:

int x = 20; // first dimension 
int y = 4; // second dimension 
double v = 5.0; // fill value 

double[][] a = IntStream 
     .range(0, x) 
     .mapToObj(i -> DoubleStream.generate(() -> v).limit(y).toArray()) 
     .toArray(i -> new double[x][]);