Core Java

Create a Flexible ArrayList for Multiple Object Types in Java

In Java programming, collections like ArrayList offer powerful data structure capabilities, but traditionally they’re designed to hold a single type of object. Sometimes, there are scenarios where you might need to store objects of different types in the same list. Also, with the introduction of pattern matching in JDK 16, we can create more flexible ArrayLists capable of handling multiple object types, and retrieve them conveniently using pattern matching. This article will guide us through the process of creating an ArrayList that can hold multiple object types in Java.

1. Creating an ArrayList with Object as the Generic Type

To create an ArrayList that can hold objects of multiple types, we can use the Object class as the generic type.

1.1 Create the ArrayList

Here’s how to initialize such an ArrayList:

public class FlexibleArrayList {

    public static void main(String[] args) {
        
        ArrayList<Object> flexibleList = new ArrayList<>();
        
    }
}

1.2 Adding Data of Multiple Types

We can add elements of any type to this ArrayList since Object is the superclass of all Java classes. Here’s how we can add elements of different types:

        // Adding elements of different types
        flexibleList.add("Hello");          // Adding a String
        flexibleList.add(10);               // Adding an Integer
        flexibleList.add(3.14);             // Adding a Double
        flexibleList.add(true);             // Adding a Boolean
        flexibleList.add(LocalTime.now());  // Adding a LocalTime
        flexibleList.add(Arrays.asList(1, 2, 3));  // Adding a List

1.3 Retrieving Elements from the ArrayList with Pattern Matching

With JDK 16, Java introduced pattern matching for the instanceof operator, enabling concise and expressive code for type checking and casting. To retrieve elements from the ArrayList, we need to cast them back to their original types. We can utilize pattern matching to retrieve elements based on their type from our multi-type ArrayList.

Here’s how we can retrieve elements:

        // Retrieving objects using pattern matching
        for (Object obj : flexibleList) {
            if (obj instanceof String s) {
                // Code block if obj is a String, with s as its reference
                System.out.println("String: " + s);
            } else if (obj instanceof Integer i) {
                // Code block if obj is an Integer, with i as its reference
                System.out.println("Integer: " + i);
            } else if (obj instanceof Double d) {
                // Code block if obj is a Double, with d as its reference
                System.out.println("Double: " + d);
            } else if (obj instanceof Boolean b) {
                // Code block if obj is a Boolean, with b as its reference
                System.out.println("Boolean: " + b);
            } else if (obj instanceof LocalTime t) {
                // Code block if obj is a LocalTime, with t as its reference
                System.out.println("LocalTime: " + t);
            } else if (obj instanceof List l) {
                // Code block if obj is a List, with l as its reference  
                System.out.println("List: " + l);
            } else {
                // Code block if obj is of another type
            }
        }

In the above code, we iterate through the ArrayList and use pattern matching to check the type of each object. Each if statement checks if the obj is an instance of a specific type using the instanceof operator. If the check succeeds, it performs a type cast and assigns the casted value to a new variable.

Depending on the type of the object, different code blocks are executed. For example:

  • If the object is a String, it prints the value of the string.
  • If it’s an Integer, it prints the value of the integer.
  • Similarly, for Double, Boolean, LocalTime, and List.

If we run the program, we will get the following output:

Fig 1: Output from using arraylist to store multiple object types in Java
Fig 1: Output from using ArrayList to store multiple object types in Java

2. Add CustomObject to the ArrayList

To add a custom object to the ArrayList, we can follow these steps:

  1. Define a custom object class.
  2. Create instances of our custom object.
  3. Add this instance to the ArrayList.

Here’s how we can modify the example to include a custom object:

// Define a custom object class
class CustomObject {

    private String name;

    public CustomObject(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
ArrayList<Object> flexibleList = new ArrayList<>();
flexibleList.add(new CustomObject("Array with Multiple Data types")); // Adding a CustomObject
else if (obj instanceof CustomObject customObj) {
                // Code block if obj is a Custom Object, with customObj as its reference  
                System.out.println("CustomObject: " + customObj.getName());
            }

3. Alternate Approach

Besides using the Object class as the generic type, there are several alternative approaches to create a ArrayList that can hold multiple object types in Java.

3.1 Using External Libraries

We can use external libraries like Google’s Guava, which provide specialized collections to handle heterogeneous data more efficiently and with better type safety. Here is an example using Guava:

An example pom.xml file for a project using Guava looks like this:

    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>31.0.1-jre</version>
        </dependency>
    </dependencies>
public class GuavaExample {

    public static void main(String[] args) {
        Multimap<String, Object> multiTypeList = ArrayListMultimap.create();
        
        // Adding elements of different types
        multiTypeList.put("String", "Hello");                           // Adding a String
        multiTypeList.put("Integer", 10);                               // Adding an Integer
        multiTypeList.put("Double", 3.14);                              // Adding a Double
        multiTypeList.put("Boolean", true);                             // Adding a Boolean
        multiTypeList.put("LocalTime", LocalTime.now());                // Adding a LocalTime
        multiTypeList.put("List", Arrays.asList(1, 2, 3));              // Adding a List
        multiTypeList.put("CustomObject", new CustomObject("CustomObject")); // Adding a CustomObject
        
        // Retrieving elements
        for (String key : multiTypeList.keySet()) {
            List<Object> values = (List<Object>) multiTypeList.get(key);
            System.out.println(key + ": " + values);
        }
    }
    
    // Define a custom object class
    static class CustomObject {
        private String name;

        public CustomObject(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

In this example, instead of using ArrayList<Object>, we are using Guava’s ArrayListMultimap, which allows us to associate multiple values with a single key. This allows us to categorize objects by type while still storing them in a single data structure.

4. Considerations

While using Object for a multi-type ArrayList provides flexibility, it comes with a trade-off of losing type safety. You need to be cautious while retrieving elements, ensuring they are of the expected types to avoid runtime errors like ClassCastException. Additionally, it’s essential to maintain clear documentation or naming conventions to indicate the types of objects stored in the list.

5. Conclusion

In this article, we explored the capabilities of ArrayList for accommodating data of different types. In Java, creating an ArrayList capable of holding objects of multiple types involves using the Object class as the generic type. This approach offers flexibility but requires careful handling to ensure type safety during data retrieval.

6. Download the Source Code

This was a tutorial on how to use an ArrayList to store multiple object types in Java.

Download
You can download the full source code of this example here: How to use an ArrayList to store multiple object types in Java

Omozegie Aziegbe

Omos holds a Master degree in Information Engineering with Network Management from the Robert Gordon University, Aberdeen. Omos is currently a freelance web/application developer who is currently focused on developing Java enterprise applications with the Jakarta EE framework.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button