Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Easier ways to handle arrays -- plus a little string manipulation

Find the middle ground between primitive arrays and Vectors, and string manipulation methods that help suppress homesickness for Perl

  • Print
  • Feedback
Primitive arrays in Java are not very object-oriented. You can get around this shortcoming by using a Vector, but, as I'll explain in more detail below, this is often overkill. The first tool I will introduce is a simple object-oriented wrapper for a primitive array. After discussing arrays, I will move on to the second tool, a pair of little string manipulation routines that I use for splitting and joining, and that have come in handy for me many times.

Dealing with arrays can be a hairy business. You want to use primitive arrays for fast access and low memory overhead, but you don't always know how big an array has to be until it's already populated. You can use a Vector, but doing so means that each primitive value must be wrapped in an object. For example, any int has to be wrapped in an Integer object. But don't lose heart -- there is a happy medium, and that is this month's first tool.

Object wrappers for dynamic arrays

Here's a scenario with which I am commonly confronted: I need to populate an array of primitive values (usually ints). However, I don't know how many values there are until after I've already cycled through them -- thus, I don't know in advance at which size I should initialize the array.

For the sake of the following code examples, let us assume that rset is the object from which I will be extracting the integer values. However, rset does not provide any size, length, or count methods that would tell me how many values it contains.

Problems with primitives

The first solution that comes to mind, from my old days of C hacking, is to declare a very large array, populate it with the values, and then trim it down. Here's how that would look in Java:

    public int[] method01( SomeContainer rset )
    {
        int[] bigArray = new int[ 1024 ];
        int count = 0;
        while( rset.next() )
        {   
            bigArray[ count ] = rset.getInt();
            count += 1;
        }
        int[] smallArray = new int[ count ];
        System.arraycopy( bigArray, 0, smallArray, 0, smallArray.length );
        return smallArray;
    }


If you chose to implement this code, the obvious downfall here would be that the actual number of values could be even greater than your initial estimate. That would result in an ArrayOutOfBoundsException, and you'd be in big trouble. Such an exception is known as a runtime exception. If you expect it, you can attempt to catch it in your code; more often than not, however, you wouldn't see such an error until the application was running.

If you were dead set on using this method, you could make it safer, by which I mean that you would prevent the occurence of the dreaded out-of-bounds exception. In order to do so, you would have to catch the array when it was about to overflow, and then increase the size of the array to accommodate the excess data. There isn't really a growing utility in Java per se, so what you would have to do is create a second, bigger array and copy over the full array. Here's how:

    public int[] method01( SomeContainer rset )
    {
        int[] bigArray = new int[ 1024 ];
        int count = 0;
        while( rset.next() )
        {             if( count >= bigArray.length ) // time to grow!
            {
                int[] tmpArray = new int[ bigArray.length + 1024 ];
                System.arraycopy( bigArray, 0, tmpArray,
                  0, bigArray.length );
                bigArray = tmpArray;
            }  
            bigArray[ count ] = rset.getInt();
            count += 1;
        }
        int[] smallArray = new int[ count ];
        System.arraycopy( bigArray, 0, smallArray, 0, smallArray.length );
        return smallArray;
    }


Vexing Vectors

Of course, there is a cleaner and more object-oriented solution to dealing with arrays. Java has provided us with a dynamic array mechanism called the Vector. You simply put objects into the Vector, and it grows as needed. You can't directly place primitives into a Vector, however; the primitive values must be wrapped in objects. Thankfully, Java has provided us with wrapper objects for all of the primitives. Using the Integer object to wrap the int and storing it into a Vector dramatically cleans up our code:

  • Print
  • Feedback

Resources