142

Hypothetically, I have 5 string array objects:

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

and I want another array object to contain those 5 string array objects. How do I do it? Can I put it in another array?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Terence Ponce
  • 9,123
  • 9
  • 31
  • 37

4 Answers4

182

Like this:

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

or

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

(The latter syntax can be used in assignments other than at the point of the variable declaration, whereas the shorter syntax only works with declarations.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Could you explain further what the second syntax does? It's kind of unclear to me. – Terence Ponce Jan 24 '11 at 11:04
  • 5
    @Terence: It does the same as the first: It creates an array of string array references, initialized to the values array1, array2, array3, array4 and array5 - each of which is in itself a string array reference. – Jon Skeet Jan 24 '11 at 11:05
  • 1
    Quick question: How will I do this at run time if I have no idea how many array objects will be created? – Terence Ponce Jan 24 '11 at 11:30
  • 1
    @Terence: Can you give a more specific example? When you're specifying the initial values at compile-time, you *do* know the size. Do you mean something like `new String[10][]`? – Jon Skeet Jan 24 '11 at 11:32
  • Yes. Similar to Peter's answer. – Terence Ponce Jan 24 '11 at 11:36
  • @JonSkeet can this be helpful in any way when trying to perform a cartesian product of a long list of api paramerters ? – valik Jul 04 '18 at 07:51
  • @valik: In that case I'd consider creating a class to represent "the set of parameters" instead of using an array. – Jon Skeet Jul 04 '18 at 11:52
  • https://stackoverflow.com/questions/51161762/how-to-implement-a-cartesian-product-of-api-parameters @JonSkeet i would direct u to my question if you have an idea please comment – valik Jul 04 '18 at 22:55
  • @Terence, you would write something like: `String[][] arrays = { {"A", "1"}, {"B", "2"}, {"C", "3"}, {"D", "4"}, {"E", "5"} };` – Ikem Krueger Oct 10 '21 at 16:51
86

try

String[][] arrays = new String[5][];
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    this one is more flexiable – hetaoblog May 19 '13 at 02:29
  • Shouldn't you define a fixed size on your array? – Filip Aug 08 '13 at 11:07
  • @Filip it is fixed to 5. Setting the next level pre-allocates them but this can be changed so setting it might not be useful. – Peter Lawrey Aug 08 '13 at 12:56
  • 8
    How do I insert data into the array? If its dynamic data? – praxmon May 15 '15 at 06:55
  • 2
    @PrakharMohanSrivastava you can set the elements individually: `arrays[0] = new String[] {"a", "b", "c"}` or use a temp List:
    
    List myList = new ArrayList<>();
    myList.add(new String[]{"a", "b", "c"});
    myList.add(new String[]{"d", "e", "f"});
    myList.toArray(arrays);
    
    – kntx Aug 17 '18 at 11:05
31

While there are two excellent answers telling you how to do it, I feel that another answer is missing: In most cases you shouldn't do it at all.

Arrays are cumbersome, in most cases you are better off using the Collection API.

With Collections, you can add and remove elements and there are specialized Collections for different functionality (index-based lookup, sorting, uniqueness, FIFO-access, concurrency etc.).

While it's of course good and important to know about Arrays and their usage, in most cases using Collections makes APIs a lot more manageable (which is why new libraries like Google Guava hardly use Arrays at all).

So, for your scenario, I'd prefer a List of Lists, and I'd create it using Guava:

List<List<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("abc","def","ghi"));
listOfLists.add(Lists.newArrayList("jkl","mno","pqr"));
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • A bit more complicated than String[ ][ ], but permits more operations such as concatenating data. However, your solution does not ensure the size of the data, which can be a problem. – Benj Nov 28 '12 at 21:37
  • 1
    @Benj if necessary, it is always possible to write a List decorator that only accepts a certain number of items. – Sean Patrick Floyd Nov 29 '12 at 09:56
  • Exact, decorators/wrappers are a good way to ensure coherence. Thus, the way we are speaking about is far more complex than simple arrays. What I have done is a small utility class Array2D which encapsulates some basic methods such as exixts(...) etc. I posted this below. – Benj Nov 29 '12 at 13:54
6

there is the class I mentioned in the comment we had with Sean Patrick Floyd : I did it with a peculiar use which needs WeakReference, but you can change it by any object with ease.

Hoping this can help someone someday :)

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

}

Example of how to use it :

// 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");
}
Benj
  • 1,184
  • 7
  • 26
  • 57
  • 5
    +1 for your effort, but: instead of initializing your int fields to -1 and reassigning them in the Constructor, you should make them final and assign them *only* in the Constructor. – Sean Patrick Floyd Nov 29 '12 at 16:41
  • 1
    @Sean : I modified the code (posted new one with "no-GC buffer", including your wise comment. – Benj Dec 02 '12 at 00:34