What is array data structure in Java? Properties, Example and Tutorial

Without any doubt, an array is one of the most used data structure in all programming language, including Java. Pick up any programming language be it functional, object-oriented, imperative or even scripting languages like Python, Bash, and Perl, you will always find array. That's why it's important for any programmer to have a good understanding of  array data structure. The array is used to store elements in the contiguous memory location and many C, C++ programmer can take advantage of a pointer to work with an array. In Java, there are no pointers and arrays are also a little bit different. They are the object, they have length field which denotes how many elements array can store. Arrays are created in the special memory area called heap memory in JVM, which is also created when you start the JVM. What remains same is that you can access the array element in constant time using their index, this works almost similarly in both C, C++ and Java, they start with 0 and ends at length -1, but Java array has an extra caveat that arrays index access are subject to bound check in Java.

In C, it's possible for a program to access an invalid index, mostly index higher than the size of the array. In Java such attempts will result in ArrayIndexOutOfBoundsException, this is done to protect  external memory  access from JVM due to malicious programs.




10 Points about Array in Java

In order to learn and remember some important details about array data structure in Java, I am sharing these points. These are the things which I believe every Java developer should know about the array. You may know how to iterate through an array using enhanced for loop or how to sort an array using Arrays.sort() method, but if you don't know fundamentals, it's very unlikely you would be able to write clean and robust code. Even if you know everything about array in Java, this list may help you to revise some useful details.

1. First and foremost, an array is an object in Java. They are not primitive like int, short, or long, but they are also not full featured object with lot of methods, but because they are object, they implicitly extend Object and that's why you can call any method of java.lang.Object using array reference e.g. toString().

10 Points about Array data structure in Java
2. Another most important thing to know about array in Java is that once created you can not change the size of the array. Curious developers may ask that then how do we have a dynamic collection like ArrayList in Java, which can resize itself when it get full? Well, it's not the resize you think, where you can simply increase the size of an array to accommodate additional elements. In order to increase size, you have to create a new array and copy contents from the old array to new array. Though there are fast methods exists to copy elements from one array to another, it still an expensive operation and can slow down the performance of your Java application. That's why initializing array or collection with proper size is still one of the best practices to follow.


3. The third thing to know about array is its length property, which tells you the size of an array or how many elements it can hold. It's often a cause of confusion as well because String has a similar length() method, yes that's a method and array length is property, so no more parenthesis. One more thing which increases this confusion is the size() method of ArrayList, which also returns how many elements ArrayList can hold. Here is a sample code snippet to find out the length of an array in Java.

 int[] arrayOfInts = new int[] { 101, 102, 103, 104, 105 };
System.out.println("length of arrayOfInts is : " + arrayOfInts.length);  // print 5

You can use the length of an array while looping through an array in Java to avoid accessing invalid indexes, as shown in next example.

4. Array index starts from zero, so the index of the first element is 0 and index of the last element is length -1. This property is used to iterate over all elements in a for loop.

      String[] cities = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};
     
       for(int i=0;  i<cities.length;  i++){
           String city = cities[i];
           System.out.println("Current city is @ " + city);
       }

Output :
Current city is @ London
Current city is @ Paris
Current city is @ NewYork
Current city is @ HongKong
Current city is @ Tokyo

You can see that we are starting the loop from 0 (first element) and ending it less than length e.g. length -1 (last element index). If you try to access array[length], you will get ArrayIndexOutOfBoundsException because the last index is length-1.

5. As I said before that arrays are treated as objects by the Java Virtual Machine.  The type of an array is "[elementtype", where element type is the type of the elements.  For example, a (1-dimensional) array of integers has type "[I", similarly one dimensional short array has type "[S", and one dimensional float array has type "[F". For two-dimensional arrays, you get two "[[" e.g. two dimensional int array has type "[[I". You can check this by yourself when you print an array in Java. It prints its element type and hashcode as shown below.

public class PrintArrayTypes{

    public static void main(String args[]) {

        // type of one dimensional array in Java
        int[] arrayOfInts = new int[] { 101, 102, 103, 104, 105 };
        System.out.println(arrayOfInts);

        short[] arrayOfShorts = new short[] { 20, 30, 40, 50, 60 };
        System.out.println(arrayOfShorts);

        float[] arrayOfFloats = new float[] { 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
        System.out.println(arrayOfFloats);

        // type of two dimensional array in Java
        int[][] arrayOfArrayOfInts = { { 1, 2, 3 }, { 10, 20, 30 },
                { 100, 200, 300 } };
        System.out.println(arrayOfArrayOfInts);

        double[][] arrayOfArrayOfDoubles = { { 2.0, 3.0 }, { 4.0, 5.0 } };
        System.out.println(arrayOfArrayOfDoubles);

    }

}

Output
[I@1693b52b
[S@3b5b25a1
[F@5d038b78
[[I@7b9a29
[[D@32c5f9fe


6. If you have been following my last example, then you will notice that printing array using toString() will not result in anything useful except that element-type. Ideally, we would like to see elements of an array in the order they exists. Can we override toString() method of array class, no that's not an option, but don't worry we have got a utility class java.util.Arrays which contains several methods to help with different types of arrays. We can use toString() and deepToString() method of Arrays class to print elements of an array for one and multi-dimensional array in Java, as shown here.

What is array in Java, properties and example


7. Similar to toString(), equals() method of array is also no use. In most cases we would like to compare elements of array and their order to another array and their elements, but equals() method of array doesn't do that, instead it does reference comparison and returns true only if both variables are pointing to same array object, as shown in below example. But don't worry Arrays class got equals() and deepEquals() method to compare elements of one-dimensional and multidimensional arrays in Java. You can infer same understanding by the following example :

public class ArrayEquality{

    public static void main(String args[]) {

       String[] cities = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};
       String[] metros = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};
       String[] capitals = cities;
       
       // comparing array using == operator
       System.out.println("cities == metros : " + (cities == metros));
       System.out.println("cities == capitals : " + (cities == capitals));
       
       
       // comparing array using equals() method
       System.out.println("cities.equals(metros) : " + cities.equals(metros));
       System.out.println("cities.equals(capitals) : " + cities.equals(capitals));
     

       // comparing array using Arrays.equals() method
       System.out.println("Arrays.equals(cities, metros) : " + Arrays.equals(cities, metros));
       System.out.println("Arrays.equals(cities, capitals) : " + Arrays.equals(cities, capitals));
       
    }

}

Output :
cities == metros : false
cities == capitals : true
cities.equals(metros) : false
cities.equals(capitals) : true
Arrays.equals(cities, metros) : true
Arrays.equals(cities, capitals) : true

You can see that first statement is false even though elements and their orders are same, because "==" operator only returns true if both variables is pointing to the same array, which is the case in second equality check. Similarly equals() method also mimic the behavior of == operator because array doesn't override Object's equals() method whose default behavior is to decide equality based upon the same reference. Arrays.equals() is the right method to check if two arrays are equal in Java or  not. You should always use that for this purpose. 


8) For checking equality of two multi-dimensional array Java programmer should always use deepEquals() method, because even Arrays.equals() method doesn't perform the deep comparison. It only does shallow equality check. Here is an example to check equality of multi-dimensional array in Java:

public class MultiDimensionalArray{

    public static void main(String args[]) {

       int[][] a1 = { {2,4}, {4,6}, {8,10} };
       int[][] a2 = { {12,14}, {14,16}, {18,20} };
       int[][] a3 = { {2,4}, {4, 6}, {8,10} };
       
       // checking if two multi-dimensional array of same length but different element equal or not
       boolean result = Arrays.deepEquals(a1, a2);
       System.out.println("Does two dimensional array a1 and a2 are equal : " + result);
       
       
       // checking if two multi-dimensional array of same length, elements equal or not
       result = Arrays.deepEquals(a1, a3);
       System.out.println("Does two dimensional array a1 and a3 are equal : " + result);
       
    }

}

Output :
Does two dimensional array a1 and a2 are equal : false
Does two dimensional array a1 and a3 are equal : true

9) While working in Java, you will need to convert between static array to dynamic array or ArrayList to array multiple times. It's good to know how you can do that quickly and this tip will help you a lot.


10)  there are several ways to initialize arrays in Java. You can either create them without initializing, in that case all buckets will hold default value of element type e.g. if you create an empty array and don't initialize it then all bucket will hold zero, because that's a default value of integer variable in Java. Similarly boolean array by default initialized with false values and String arrays are initialized with null values. If you know the values in advance you can initialize array at the time of creation itself as shown below:

 int[] numbers = {12345}; // valid
int multipleOfThree[] = {3, 6, 9, 12, 15}; // valid 
int[] even = new int[]{2, 4, 6, 8, 10}; // valid


11) One bonus tip is that Array is quite different than ArrayList in the sense that later is a dynamic array, it can resize itself when need. On the other hand, you can not change the size of Array once created. Apart from this very fact, there are several other difference between these two classes e.g. ArrayList is part of Java Collection framework but Array is not. See here to learn several more differences between Array and ArrayList in Java


That's all on this list of some important points about array data structure in Java. Use array to hold same type of elements e.g. integers, strings or object, but you can not mix them e.g. Java array can not hold both integer and string at same time. At  compile time it's error but for objects if compiler will allow it will throw ArrayStoreException at runtime. On same note, array is also one of the fasted data-structure for accessing elements if you know the index. Several higher level data structures like HashMap and HashSet are built on top of array because of it's O(1) get performance.


3 comments:

  1. ArrayIndexOutOfBounds in Java is a way to prevent BufferOverFlow errors, which can cause a malicious program to store something in a memory location which is not guarded. Java doesn't allow BufferOverFlow error to happen and for this it does bounds check on array, no pointers only helps the cause.

    ReplyDelete
  2. Couple of more points about Java array, they are homogenous, you cannont store an int into String array, it will compile time error, but an Object array can store anything, but if a String array stores an object other than String it will throw ArrayStoreException at runtime.

    ReplyDelete
  3. Nice tip on Arrays#equals and #deepEquals methods. Thank you very much.

    ReplyDelete