Cách tạo một mảng mảng trong Java


115

Theo giả thuyết, tôi có 5 đối tượng mảng chuỗi:

String[] array1 = new String[];
String[] array2 = new String[];
String[] array3 = new String[];
String[] array4 = new String[];
String[] array5 = new String[];

và tôi muốn một đối tượng mảng khác chứa 5 đối tượng mảng chuỗi đó. Tôi phải làm nó như thế nào? Tôi có thể đặt nó trong một mảng khác không?


43
Câu hỏi của Noob có thể nghiêm trọng. Trên thực tế, chúng thường xuyên như vậy. :-)
TJ Crowder

3
Câu hỏi thích hợp và câu trả lời không rõ ràng đối với những người biết cách căn chỉnh bộ nhớ được thực hiện. +1
Benj

Câu trả lời:


153

Như thế này:

String[][] arrays = { array1, array2, array3, array4, array5 };

hoặc là

String[][] arrays = new String[][] { array1, array2, array3, array4, array5 };

(Cú pháp thứ hai có thể được sử dụng trong các phép gán khác với điểm khai báo biến, trong khi cú pháp ngắn hơn chỉ hoạt động với các khai báo.)


Bạn có thể giải thích thêm cú pháp thứ hai không? Tôi không rõ lắm.
Terence Ponce

4
@Terence: Nó thực hiện tương tự như cách đầu tiên: Nó tạo ra một mảng tham chiếu mảng chuỗi, được khởi tạo thành các giá trị array1, array2, array3, array4 và array5 - mỗi giá trị trong số đó là một tham chiếu mảng chuỗi.
Jon Skeet

1
Câu hỏi nhanh: Tôi sẽ thực hiện việc này như thế nào tại thời điểm chạy nếu tôi không biết có bao nhiêu đối tượng mảng sẽ được tạo?
Terence Ponce

1
@Terence: Bạn có thể cho một ví dụ cụ thể hơn không? Khi bạn đang xác định giá trị ban đầu tại thời gian biên dịch, bạn làm biết kích thước. Bạn có nghĩa là một cái gì đó như thế new String[10][]nào?
Jon Skeet

Đúng. Tương tự như câu trả lời của Peter.
Terence Ponce,

71

thử

String[][] arrays = new String[5][];

1
cái này là flexiable hơn
hetaoblog

Bạn không nên xác định kích thước cố định trên mảng của mình?
Filip

@Filip nó được cố định thành 5. Đặt cấp độ tiếp theo sẽ phân bổ trước chúng nhưng điều này có thể được thay đổi nên việc đặt nó có thể không hữu ích.
Peter Lawrey

8
Làm cách nào để chèn dữ liệu vào mảng? Nếu dữ liệu động của nó?
Prakhar Mohan Srivastava

1
@PrakharMohanSrivastava bạn có thể đặt các phần tử riêng lẻ: arrays[0] = new String[] {"a", "b", "c"}hoặc sử dụng Danh sách tạm thời: <pre> <code> List <String []> myList = new ArrayList <> (); myList.add (new String [] {"a", "b", "c"}); myList.add (new String [] {"d", "e", "f"}); myList.toArray (mảng); </code> </pre>
kntx

26

Mặc dù có hai câu trả lời tuyệt vời cho bạn biết cách thực hiện, tôi cảm thấy rằng còn thiếu một câu trả lời khác: Trong hầu hết các trường hợp, bạn hoàn toàn không nên làm.

Mảng rất cồng kềnh, trong hầu hết các trường hợp, bạn nên sử dụng API Bộ sưu tập .

Với Bộ sưu tập, bạn có thể thêm và xóa các phần tử và có các Bộ sưu tập chuyên biệt cho các chức năng khác nhau (tra cứu dựa trên chỉ mục, sắp xếp, tính duy nhất, truy cập FIFO, đồng thời, v.v.).

Mặc dù tất nhiên là tốt và quan trọng khi biết về Mảng và cách sử dụng của chúng, nhưng trong hầu hết các trường hợp, việc sử dụng Bộ sưu tập làm cho các API dễ quản lý hơn rất nhiều (đó là lý do tại sao các thư viện mới như Google Guava hầu như không sử dụng Mảng).

Vì vậy, đối với tình huống của bạn, tôi thích một Danh sách các Danh sách hơn và tôi sẽ tạo nó bằng cách sử dụng Guava:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));

Phức tạp hơn một chút so với String [] [], nhưng cho phép nhiều hoạt động hơn như nối dữ liệu. Tuy nhiên, giải pháp của bạn không đảm bảo kích thước của dữ liệu, đó có thể là một vấn đề.
Benj

1
@Benj nếu cần thiết, luôn có thể viết trình trang trí Danh sách chỉ chấp nhận một số mục nhất định.
Sean Patrick Floyd

Chính xác, trình trang trí / trình bao bọc là một cách tốt để đảm bảo tính mạch lạc. Do đó, cách chúng ta đang nói phức tạp hơn nhiều so với các mảng đơn giản. Những gì tôi đã làm là một lớp tiện ích nhỏ Array2D <T> đóng gói một số phương thức cơ bản như exixts (...), v.v. Tôi đã đăng cái này bên dưới.
Benj

6

có lớp tôi đã đề cập trong nhận xét mà chúng tôi đã có với Sean Patrick Floyd: Tôi đã làm nó với một cách sử dụng đặc biệt cần WeakReference, nhưng bạn có thể thay đổi nó bằng bất kỳ đối tượng nào một cách dễ dàng.

Hy vọng điều này có thể giúp ai đó một ngày nào đó :)

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;


/**
 *
 * @author leBenj
 */
public class Array2DWeakRefsBuffered<T>
{
    private final WeakReference<T>[][] _array;
    private final Queue<T> _buffer;

    private final int _width;

    private final int _height;

    private final int _bufferSize;

    @SuppressWarnings( "unchecked" )
    public Array2DWeakRefsBuffered( int w , int h , int bufferSize )
    {
        _width = w;
        _height = h;
        _bufferSize = bufferSize;
        _array = new WeakReference[_width][_height];
        _buffer = new LinkedList<T>();
    }

    /**
     * Tests the existence of the encapsulated object
     * /!\ This DOES NOT ensure that the object will be available on next call !
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     */public boolean exists( int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            T elem = _array[x][y].get();
            if( elem != null )
            {
            return true;
            }
        }
        return false;
    }

    /**
     * Gets the encapsulated object
     * @param x
     * @param y
     * @return
     * @throws IndexOutOfBoundsException
     * @throws NoSuchElementException
     */
    public T get( int x , int y ) throws IndexOutOfBoundsException , NoSuchElementException
    {
        T retour = null;
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (get) : [ y = " + y + "]" );
        }
        if( _array[x][y] != null )
        {
            retour = _array[x][y].get();
            if( retour == null )
            {
            throw new NoSuchElementException( "Dereferenced WeakReference element at [ " + x + " ; " + y + "]" );
            }
        }
        else
        {
            throw new NoSuchElementException( "No WeakReference element at [ " + x + " ; " + y + "]" );
        }
        return retour;
    }

    /**
     * Add/replace an object
     * @param o
     * @param x
     * @param y
     * @throws IndexOutOfBoundsException
     */
    public void set( T o , int x , int y ) throws IndexOutOfBoundsException
    {
        if( x >= _width || x < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ x = " + x + "]" );
        }
        if( y >= _height || y < 0 )
        {
            throw new IndexOutOfBoundsException( "Index out of bounds (set) : [ y = " + y + "]" );
        }
        _array[x][y] = new WeakReference<T>( o );

        // store local "visible" references : avoids deletion, works in FIFO mode
        _buffer.add( o );
        if(_buffer.size() > _bufferSize)
        {
            _buffer.poll();
        }
    }

}

Ví dụ về cách sử dụng nó:

// a 5x5 array, with at most 10 elements "bufferized" -> the last 10 elements will not be taken by GC process
Array2DWeakRefsBuffered<Image> myArray = new Array2DWeakRefsBuffered<Image>(5,5,10);
Image img = myArray.set(anImage,0,0);
if(myArray.exists(3,3))
{
    System.out.println("Image at 3,3 is still in memory");
}

4
1 cho nỗ lực của bạn, nhưng: thay vì khởi tạo các lĩnh vực int của bạn để -1 và giao lại trong Constructor, bạn nên làm cho họ thức và gán chúng chỉ trong Constructor.
Sean Patrick Floyd

1
@Sean: Tôi đã sửa đổi mã (đã đăng một mã mới với "bộ đệm no-GC", bao gồm cả nhận xét khôn ngoan của bạn.
Benj
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.