October 25, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Objects and Collections: Vectors

  • August 3, 2006
  • By Matt Weisfeld
  • Send Email »
  • More Articles »

Introduction

This series, The Object-Oriented Thought Process, is intended for someone just learning an object-oriented language and who wants to understand the basic concepts before jumping into the code, or someone who wants to understand the infrastructure behind an object-oriented language he or she is already using. These concepts are part of the foundation that any programmer will need to make the paradigm shift from procedural programming to object-oriented programming.

Click here to start at the beginning of the series.

In keeping with the code examples used in the previous articles, Java will be the language used to implement the concepts in code. One of the reasons that I like to use Java is because you can download the Java compiler for personal use at the Sun Microsystems Web site http://java.sun.com/. You can download the standard edition, J2SE 5.0, at http://java.sun.com/j2se/1.5.0/download.jsp to compile and execute these applications. I often reference the Java J2SE 5.0 API documentation and I recommend that you explore the Java API further. Code listings are provided for all examples in this article as well as figures and output (when appropriate). See the first article in this series for detailed descriptions for compiling and running all the code examples.

In the previous column, you moved from the topic of primitives (basically the low-level system variables), objects, and wrappers to the concept of collections. To begin the discussion on the relationship between objects and collections, you covered the topic of arrays, perhaps the original collection.

In many ways, you are covering a bit of history as you make your way through the topic of collections. Although arrays may be the original collection, there are now certainly many different types of collections to consider. In the beginning, Java did not include a collection framework. Over the past 10 years or so, collections have been added and others have become obsolete. The way to process certain collections also has evolved in different ways.

Because you are focusing more on conceptual matters in this column, you often take a different approach when inspecting actual code. Instead of looking at the code from a purely technical perspective, you can step back and consider some of the reasons why certain design decisions were made. For example, why were some collections introduced and why did certain ones become obsolete?

As already stated, you want to take a historical perspective, as well as one that is purely technical. Curiously enough, this approach also has a solid technical basis. There are many people who wonder what the advantage is to learning technical implementations that are considered obsolete. In the software industry, most cutting-edge developers want to work on cutting-edge code. This is understandable. However, there are two compelling technical reasons why developers should study code that may have recently been deemed obsolete — testing and maintenance.

I often stress to my students that they need to be prepared to encounter all sorts of code — not just the latest technology. All developers are involved in maintenance, which involves bug fixing or enhancements. Often, code that is being maintained may have been in production for quite a while.

In the case of Java, the code could potentially be up to a decade old. When testing, a developer may need to test with code that may be just as old. In any event, a developer must be aware of the historical evolution of the system being worked with. Although there are certainly more recent collections available to developers, Arrays and Vectors are important constructs that need to be understood.

In this column, I will discuss processing techniques for Vectors, a few of which have become obsolete. However, understanding the code when you do see it is important. Although I have stated that the Array may be the original collection, it may not be the best or most efficient. Take a look at some of the limitations of the Array and see what has evolved over time to address some of these limitations.

Arrays

Baseline

First, you should revisit the code from the last column. The code in Listing 1 creates a very simple array called items and then prints out the contents of the array. Compile and execute this code to verify that your system is working properly. You will use this as the baseline for the remainder of the article.

public class TestArray {
   public static void main(String[] args) {
      int[] items = {0,1,2,3,4};
      for (int i = 0; i<5; i++) {
         System.out.println("items[" + i + "]=" + items[i]);
      }
   }
}

Listing 1: TestArray.java

When this application is executed, you should get the following output (the actual program output is in bold).

C:column25>"C:Program FilesJavajdk1.5.0_06binjava" TestArray
items[0]=0
items[1]=1
items[2]=2
items[3]=3
items[4]=4
C:column25>

Array Limitations

Although arrays have been used successfully for about as long as computer languages have existed, there is one obvious drawback to arrays — their size is static. In other words, the size of an array, once defined, cannot change. This leads to two obvious problems.

First, consider the code in Listing 1. The size of the array items is determined by the compiler to be 5. In this simple application, this works. However, most applications are not quite as simple, and you quickly can run into problems. What if, after the application is running, you find out that you need a sixth, or seventh, item in the array? There is nothing that you can do. To allow a sixth or seventh item in the array, you must update and recompile the code and then re-distribute the application.

Second, if it turns out that you only needed two of the items in the array, there is no way to free-up the memory of the unused thee array items. In this case, that means that the space for three integers will be lost for the remainder of the run of the application. 32 bits are used to store a Java integer. That means that in this example, there would be 96 (32*3) bits of unused (basically lost) memory.

You might wonder what the concern is because 96 bits is not really that much memory. The problem becomes more acute when you have large arrays that are created multiple times. For example, assume that you have an application that creates an array of 100 elements for 1000 customers. Further assume that the customers use an average of only 50 elements. That means that, on average, 50 elements for each of the 1000 customers will be unused.

Doing the math, you can determine that for the 50000 unused elements you have 1,600,000 bits (32*50,000) that are not available to the computer system. With the proliferation of small devices, such as phones, PDAs, and others, the footprint (size) of the code can be very important. Even a small amout of memory can make a difference.

One question might be: If you only use an average of 50 elements per customer, why don't you just make the array size 50? The key word is average. If only a single customer needs 100 elements, the array must be of size 100. In short, the array must be the size of the largest possible situation; otherwise, it won't work in that instance.

The essence of this discussion is that the array fails on both counts. If the array is too large, it wastes memory. If the array is too short, it simply won't work. Sizing an array is really a guess.

Vectors

A Better Array?

Based on the discussion in the previous section, what would be a logical proposal that would greatly enhance the functionality of an array? The answer: Design the array so that the array can change its size, or more succinctly, design an array that can dynamically grow based on the needs of the application. The word dynamically is key here because it implies that the array will change during the execution of the application. This means that the size of the array is not determined at compile time.

What makes this even more interesting is the fact that the concept of doing business dynamically is fundamental to the Java and .NET models specifically, and, in more fundamental ways, the object-oriented paradigm itself. Creating things dynamically requires that the functions such as memory allocation and network connection be dealt with at runtime. Thus, as you go in search of an improved array, you are looking for an array that will allow you to obtain memory only when you need it.

When the collection framework was first released, a collection called a Vector was included. The Java documentation (v1.3) definition presents the hierarchy for the Vector class.

java.util: Class Vector

java.lang.Object
   |
   +--java.util.AbstractCollection
      |
      +--java.util.AbstractList
         |
         +--java.util.Vector

Note that the Vector inherits from AbstractList and AbstractCollection. Thus, a Vector is both a List and a Collection. I will discuss Lists in great detail later.

The Vector is often defined as a growable array. In fact, the Java documentation (v1.3) for the Vector describes it thus:

"The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created."

The documentation further describes how the Vector fits into the Java Collection Framework.

As of the Java 2 platform v1.2, this class has been retrofitted to implement List, so that it becomes a part of Java's collection framework. Unlike the new collection implementations, Vector is synchronized.

Now, take a look at a simple Vector application. Listing 2 presents a complete program that simply creates a Vector called myVec.

import java.io.*;
import java.util.*;

public class TestVector {
   public static void main(String[] args){
      Vector myVec = new Vector();
   }
}

Listing 2: TestVector.java

This code creates a Vector using its default constructor, which creates the Vector with an initial size of 10 elements. You can indicate a specific size by including an integer value in the constructor.

Vector myVec = new Vector(5);

With this syntax, it would seem that the Vector could be just like an Array.

import java.io.*;
import java.util.*;

public class TestVector {
   public static void main(String[] args){
      Vector myVec = new Vector();
         myVec[1] = 5;

   }
}

Listing 3: TestVector.java

However, as you might suspect, it is not quite this simple. When you compile this code, the following error message is generated.

C:column25>"C:Program FilesJavajdk1.5.0_06binjavac"
   -classpath . TestVector.java
TestVector.java:8: array required, but java.util.Vector found
   myVec[1] = 5;
     ^
1 error
C:column25>

The Vector is not treated as an Array at all. In fact, it is important to notice that the Array uses the square brackets []. So, in this case, when the compiler encounters the square brackets [], it expects an array.

You need to think of a Vector in an entirely different way.





Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel