Featured Whitepapers
Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

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

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
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:

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comment
Login
Forgot your account info?
Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources