Java Data Structures: Powerful Tools for Managing Data

Discover the powerful data structures provided by the Java utility package, designed to handle a variety of data management tasks. This guide covers essential interfaces and classes, including Enumeration, BitSet, Vector, Stack, Dictionary, Hashtable, and Properties. Learn how to leverage these data structures to enhance the efficiency and performance of your Java applications.



Java - Data Structures

The data structures provided by the Java utility package are quite powerful and serve a variety of functions. The following are some important interfaces and classes:

  • Enumeration
  • BitSet
  • Vector
  • Stack
  • Dictionary
  • Hashtable
  • Properties

All these classes are considered legacy, as Java 2 introduced a new framework called the Collections Framework, which will be discussed in the next chapter.

The Enumeration

The Enumeration interface is not a data structure itself, but it is essential in the context of other data structures. It defines a method to retrieve successive elements from a data structure.

For example, the nextElement method is used to get the next element in a data structure containing multiple elements.

Example

Syntax

    import java.util.Vector;
    import java.util.Enumeration;
    
    public class EnumerationTester {
        public static void main(String args[]) {
            Enumeration days;
            Vector dayNames = new Vector<>();
            
            dayNames.add("Sunday");
            dayNames.add("Monday");
            dayNames.add("Tuesday");
            dayNames.add("Wednesday");
            dayNames.add("Thursday");
            dayNames.add("Friday");
            dayNames.add("Saturday");
            days = dayNames.elements();
            
            while (days.hasMoreElements()) {
                System.out.println(days.nextElement()); 
            }
        }
    }
    
Output

    Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    

The BitSet

The BitSet class represents a group of bits or flags that can be individually set and cleared. This class is useful when you need to manage a set of Boolean values; each value corresponds to a specific bit that you can set or clear as needed.

Example

Syntax

    import java.util.BitSet;
    
    public class BitSetDemo {
        public static void main(String args[]) {
            BitSet bits1 = new BitSet(16);
            BitSet bits2 = new BitSet(16);
            
            for(int i = 0; i < 16; i++) {
                if((i % 2) == 0) bits1.set(i);
                if((i % 5) != 0) bits2.set(i);
            }
            
            System.out.println("Initial pattern in bits1: ");
            System.out.println(bits1);
            System.out.println("\nInitial pattern in bits2: ");
            System.out.println(bits2);
            
            bits2.and(bits1);
            System.out.println("\nbits2 AND bits1: ");
            System.out.println(bits2);
            
            bits2.or(bits1);
            System.out.println("\nbits2 OR bits1: ");
            System.out.println(bits2);
            
            bits2.xor(bits1);
            System.out.println("\nbits2 XOR bits1: ");
            System.out.println(bits2);
        }
    }
    
Output

    Initial pattern in bits1:
    {0, 2, 4, 6, 8, 10, 12, 14}
    
    Initial pattern in bits2:
    {1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14}
    
    bits2 AND bits1:
    {2, 4, 6, 8, 12, 14}
    
    bits2 OR bits1:
    {0, 2, 4, 6, 8, 10, 12, 14}
    
    bits2 XOR bits1:
    {}
    

The Vector

The Vector class is similar to a traditional Java array but can grow as necessary to accommodate new elements. Like arrays, the elements of a Vector object can be accessed via an index.

The advantage of using the Vector class is that you don't need to define its size upon creation; it automatically adjusts its size as needed.

Example

Syntax

    import java.util.*;
    
    public class VectorDemo {
        public static void main(String args[]) {
            Vector v = new Vector(3, 2);
            System.out.println("Initial size: " + v.size());
            System.out.println("Initial capacity: " + v.capacity());
            
            v.addElement(new Integer(1));
            v.addElement(new Integer(2));
            v.addElement(new Integer(3));
            v.addElement(new Integer(4));
            System.out.println("Capacity after four additions: " + v.capacity());
            
            v.addElement(new Double(5.45));
            System.out.println("Current capacity: " + v.capacity());
            
            v.addElement(new Double(6.08));
            v.addElement(new Integer(7));
            System.out.println("Current capacity: " + v.capacity());
            
            v.addElement(new Float(9.4));
            v.addElement(new Integer(10));
            System.out.println("Current capacity: " + v.capacity());
            
            v.addElement(new Integer(11));
            v.addElement(new Integer(12));
            System.out.println("First element: " + (Integer)v.firstElement());
            System.out.println("Last element: " + (Integer)v.lastElement());
            
            if(v.contains(new Integer(3))) {
                System.out.println("Vector contains 3.");
            }
            
            Enumeration vEnum = v.elements();
            System.out.println("\nElements in vector:");
            
            while(vEnum.hasMoreElements()) {
                System.out.print(vEnum.nextElement() + " ");
            }
            System.out.println();
        }
    }
    
Output

    Initial size: 0
    Initial capacity: 3
    Capacity after four additions: 5
    Current capacity: 5
    Current capacity: 7
    Current capacity: 9
    First element: 1
    Last element: 12
    Vector contains 3.
    
    Elements in vector:
    1 2 3 4 5.45 6.08 7 9.4 10 11 12
    

The Stack

The Stack class implements a last-in-first-out (LIFO) stack of elements. You can think of a stack as a vertical pile of objects; when you add a new element, it gets stacked on top of the others. When you pull an element off the stack, it comes off the top, meaning the last element you added is the first one to come back off.

Example

The following program illustrates several of the methods supported by the Stack collection:

Syntax

import java.util.*;

public class StackDemo {
static void showpush(Stack st, int a) {
    st.push(new Integer(a));
    System.out.println("push(" + a + ")");
    System.out.println("stack: " + st);
}

static void showpop(Stack st) {
    System.out.print("pop -> ");
    Integer a = (Integer) st.pop();
    System.out.println(a);
    System.out.println("stack: " + st);
}

public static void main(String args[]) {
    Stack st = new Stack();
    System.out.println("stack: " + st);
    showpush(st, 42);
    showpush(st, 66);
    showpush(st, 99);
    showpop(st);
    showpop(st);
    showpop(st);
    try {
        showpop(st);
    } catch (EmptyStackException e) {
        System.out.println("empty stack");
    }
}
}

Output


stack: [ ]
push(42)
stack: [42]
push(66)
stack: [42, 66]
push(99)
stack: [42, 66, 99]
pop -> 99
stack: [42, 66]
pop -> 66
stack: [42]
pop -> 42
stack: [ ]
pop -> empty stack

The Dictionary

The Dictionary class is an abstract class that defines a data structure for mapping keys to values. This is useful when you want to access data via a particular key rather than an integer index. Since the Dictionary class is abstract, it provides only the framework for a key-mapped data structure rather than a specific implementation.

Example

The following example shows the usage of the Java Dictionary keys() method. We create a dictionary instance using a Hashtable object of Integer, Integer. Then we add a few elements and retrieve an enumeration of the keys:

Syntax

package com.tutorialsarena;

import java.util.Enumeration;
import java.util.Dictionary;
import java.util.Hashtable;

public class DictionaryDemo {
public static void main(String[] args) {
    // create a new hashtable
    Dictionary dictionary = new Hashtable<>();

    // add elements
    dictionary.put(1, 1);
    dictionary.put(2, 2);

    Enumeration enumeration = dictionary.keys();

    while(enumeration.hasMoreElements()) {
        System.out.println(enumeration.nextElement());
    }
}
}

Output


2
1

The Hashtable

The Hashtable class provides a means of organizing data based on a user-defined key structure. For example, in an address list hash table, you could store and sort data based on a key such as ZIP code rather than on a person's name. The specific meaning of keys with regard to hash tables is totally dependent on the usage of the hash table and the data it contains.

Example

The following example shows the usage of the Java Hashtable contains() method to check if a value is present in a Hashtable:

Syntax

package com.tutorialsarena;

import java.util.Hashtable;

public class HashtableDemo {
public static void main(String args[]) {
    // create hash table
    Hashtable hashtable = new Hashtable<>();

    // populate hash table
    hashtable.put(1, 1);
    hashtable.put(2, 2);
    hashtable.put(3, 3); 

    System.out.println("Initial table elements: " + hashtable);
    System.out.println("Hashtable contains 2 as value: " + hashtable.contains(2));
    System.out.println("Hashtable contains 4 as value: " + hashtable.contains(4));
}    
}

Output


Initial table elements: {3=3, 2=2, 1=1}
Hashtable contains 2 as value: true
Hashtable contains 4 as value: false

The Properties

The Properties class is a subclass of Hashtable. It is used to maintain lists of values in which the key is a String and the value is also a String. The Properties class is utilized by many other Java classes. For example, it is the type of object returned by System.getProperties() when obtaining environmental values.

Example

The following example shows the usage of the Java Properties getProperty(String key) method to get a value based on a key:

Syntax

package com.tutorialsarena;

import java.util.Properties;

public class PropertiesDemo {
public static void main(String[] args) {
    Properties properties = new Properties();

    // populate properties object
    properties.put("1", "tutorials");
    properties.put("2", "point");
    properties.put("3", "is best");

    System.out.println("Properties elements: " + properties);
    System.out.println("Value: " + properties.getProperty("1"));
}
}

Output


Properties elements: {1=tutorials, 2=point, 3=is best}
Value: tutorials