What is Collection Interface
The Collection interface in Java is the foundation of the Java Collections Framework. It represents a group of objects, known as elements, and provides a set of methods to manipulate and operate on these elements.
The Collection interface is a root interface that extends the Iterable interface, allowing collections to be iterated over using the enhanced for loop or Iterator interface. Since, it is root interface, polymorphically it provides maximum generality.
The AbstractCollection class in Java is an abstract base class that provides a skeletal implementation of the Collection interface. It serves as a convenient starting point for creating custom collection classes by handling common functionality and reducing the implementation effort required for concrete collection classes.
Collection interface extends another interface called Iterable interface which would enable any collection object to be used in for each loops.
Collection interface syntax as in Java API
public interface Collection<E> extends Iterable<E> {
// Basic Operations
boolean add(E e);
boolean remove(Object o);
boolean contains(Object o);
int size();
boolean isEmpty();
void clear();
// Bulk Operations
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
boolean containsAll(Collection<?> c);
void clear(); // optional, removes all elements from collection.
// Array Conversion
Object[] toArray();
<T> T[] toArray(T[] a);
// Iteration
Iterator<E> iterator();
// Stream Support (Java 8+)
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
In the above syntax, the Collection interface is defined as a generic interface (Collection<E>) that can work with elements of any specific type represented by the type parameter E.
The interface extends the Iterable interface, allowing collections to be iterated over using the enhanced for loop or the Iterator interface.
Collection interface methods
The Collection interface defines a set of methods categorized as basic operations, bulk operations, array conversion, iteration, and stream support (added in Java 8).
The basic operations include methods like add(), remove(), contains(), size(), isEmpty(), and clear(). These methods provide common functionality for adding, removing, checking the presence of elements, and managing the size and emptiness of the collection.
The bulk operations include methods like addAll(), removeAll(), retainAll(), and containsAll(). These methods allow collections to be modified based on other collections, such as adding all elements from another collection, removing elements common to another collection, retaining only elements from another collection, and checking if the collection contains all elements of another collection.
The array conversion methods toArray() and toArray(T[] a) allow the collection to be converted into an array. The first method returns an Object array, while the second method allows specifying the type of the array.
The iterator() method returns an Iterator over the elements of the collection, allowing for iteration and sequential access to the elements.
Starting from Java 8, the stream() and parallelStream() methods are provided for supporting streaming operations using the Stream API.
Concrete implementations of the Collection interface, such as ArrayList, LinkedList, and HashSet, provide additional methods and functionalities specific to their implementations.
Examples
<T> T[] toArray(T[] a) method
import java.util.ArrayList;
import java.util.List;
public class ToArrayExample {
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.add("Hello");
myList.add("World");
// Create an array of String with the same size as the list
String[] array = new String[myList.size()];
// Convert the list to an array using the toArray() method
String[] resultArray = myList.toArray(array);
// Print the elements of the resulting array
for (String element : resultArray) {
System.out.println(element);
}
}
}
In this example, we have a List of strings called myList. We want to convert this list to an array of strings using the toArray(T[] a) method.
First, we create a String array called array with the same size as the list using myList.size(). Then, we call the toArray() method on the myList object and pass array as the argument.
** The toArray(T[] a) method takes the provided array as an argument and populates it with the elements of the list. If the provided array is large enough to accommodate all the elements, it will be used. Otherwise, a new array of the same runtime type and size will be created and returned.
This usage of toArray(T[] a) allows you to convert a List or any other Collection into an array of the desired type. It provides a way to obtain an array representation of the collection’s elements, which can be useful in scenarios where you specifically need an array or want to interface with code that requires an array.
Object[] toArray()
import java.util.ArrayList;
import java.util.List;
public class ToArrayExample {
public static void main(String[] args) {
List<String> myList = new ArrayList<>();
myList.add("Hello");
myList.add("World");
// Convert the list to an array using the toArray() method
Object[] resultArray = myList.toArray();
// Print the elements of the resulting array
for (Object element : resultArray) {
System.out.println(element);
}
}
}
In this example, we have a List of strings called myList. We want to convert this list to an array of Object using the toArray() method.
We simply call the toArray() method on the myList object without passing any argument. The toArray() method returns an array of Object, where each element of the list is copied into the corresponding position of the array.
Finally, we iterate over the resulting array (resultArray) and print its elements. Since the resultArray is of type Object[], we need to use the Object type to iterate over the elements.
The toArray() method is useful when you need to obtain a generic array representation of a List or any other Collection. However, keep in mind that the resulting array will have the runtime type of Object[].
** If you require a specific type of array, you can use the overloaded toArray(T[] a) method and pass an array of the desired type.
How to enable your class objects to be iterable
To enable your class objects to be iterable, you need to implement the Iterable interface and provide an implementation of the iterator() method. This allows instances of your class to be used in enhanced for loops or with the Iterator interface for iteration.
Here’s an example of how to enable your class objects to be iterable:
import java.util.Iterator;
public class MyIterableClass<T> implements Iterable<T> {
private T[] elements;
public MyIterableClass(T[] elements) {
this.elements = elements;
}
// provide an implementation for iterator() method
@Override
public Iterator<T> iterator() {
return new MyIterator();
}
// private class implementing Iterator interface
private class MyIterator implements Iterator<T> {
private int currentIndex = 0;
@Override
public boolean hasNext() {
return currentIndex < elements.length;
}
@Override
public T next() {
return elements[currentIndex++];
}
}
// Other methods and code specific to your class
}
In the example above, the MyIterableClass implements the Iterable interface by specifying the type parameter <T>. It provides an implementation of the iterator() method that returns an instance of the custom MyIterator class.
The MyIterator class implements the Iterator interface and defines the hasNext() and next() methods required for iteration. It keeps track of the current index to provide the next element from the array of elements.
With this implementation, you can use instances of MyIterableClass in enhanced for loops or with the Iterator interface as follows:
MyIterableClass<String> iterable = new MyIterableClass<>(new String[]{"Hello", "World"});
// Using enhanced for loop
for (String element : iterable) {
System.out.println(element);
}
// Using Iterator
Iterator<String> iterator = iterable.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
By implementing the Iterable interface and providing an iterator implementation, you enable your class objects to be
- iterated over using enhanced for loops or
- by obtaining an iterator explicitly.
This allows for a more intuitive and convenient way of working with instances of your class in iterative scenarios.