ArrayList
ArrayList in Java implements List Interface. It accepts even null elements. ArrayList is not synchronized and therefore external synchronization is required while working with ArrayList in Multi-threaded environments.
We will see how to add elements and search elements from an ArrayList. Adding elements to an ArrayList is straightforward. Searching elements from an ArrayList require some knowledge about how elements are searched in an ArrayList.
Adding and Searching String Objects
Lets create an ArrayList for storing String objects and add some values to it.
//Create a list for storing Strings List<String> stringVals = new ArrayList<String>(); //Add String values to the list stringVals.add("hello"); stringVals.add("welcome"); stringVals.add("india");
Now lets try to search from this ArrayList :-
System.out.println(stringVals.contains("hello")); // prints true System.out.println(stringVals.contains("Hello")); // prints false
Below pseudo-code shows how an element is searched in an ArrayList:-
ArrayList.contains( Element o){
for(each Element e in ArrayList){
if(o.equals(e)){
return true;
}
}
return false;
}
When we search an element in the above list containing Strings, the ArrayList loops over its elements and the equals() method is called on the given element to check whether it matches with the element from the ArrayList. In our case, for the given element “hello”, equals() method (equals() method of String class) is called to check equality of elements. Since we have an element “hello” in the ArrayList, true is returned. For the element “Hello”, false is returned.
All the wrapper classes corresponding to java primitive data-types overrides equals method, therefore we need not do anything extra while using objects of these classes in ArrayList – Byte, Short, Integer, Long, Float, Double, Boolean, Character.
String class also overrides equals method and all string objects can be directly used in Java ArrayList.
Adding and Searching Custom Objects
Lets see how we can add and search custom objects in an ArrayList. Let us first create Employee class which we will use to create Employee objects.
//This class stores data for an Employee class Employee{ int id; String name; public Employee(int id, String name) { this.id = id; this.name = name; } }
Lets create an ArrayList for storing Employee Objects and add some values to it.
List<Employee> employees = new ArrayList<Employee>(); Employee e1 = new Employee(1, "Rajesh"); Employee e2 = new Employee(2, "Ankit"); employees.add(e1); employees.add(e2);
Now Lets try to search from this ArrayList :-
System.out.println(employees.contains(e1)); // prints true Employee e3 = new Employee(1, "Rajesh"); System.out.println(employees.contains(e3)); // prints false
When we try to search Employee e1 in the ArrayList, we get true. And when we create a new employee e3 with same values(1, “Rajesh”) as employee e1 and try to search it in the ArrayList we get false.
Can you figure out why this behavior is?
Lets have a look again at the pseudo-code for searching an element in the ArrayList:-
ArrayList.contains( Element o){
for(each Element e in ArrayList){
if(o.equals(e)){
return true;
}
}
return false;
}
We can see that equals method is called to check object equality. For our Employee object, equals method of our Employee class will be called. As Employee class does not override the equals method, the equals() method from parent class (Object class) will be called. This default implementation of equals() from the Object class checks for equality by just comparing the references. As Employee e1 reference is added to the list, we get true while searching for employee e1.
How can we search based on Elements values?
To search based on values, we need to override equals() method in our Employee class as shown below:-
// This class stores data for an Employee class Employee extends Object{ int id; String name; public Employee(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Employee other = (Employee) obj; if (id != other.id) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } }
Again, lets create an ArrayList for storing Employee Objects and add some values to it.
List<Employee> employees = new ArrayList<Employee>(); Employee e1 = new Employee(1, "Rajesh"); Employee e2 = new Employee(2, "Ankit"); employees.add(e1); employees.add(e2);
Now Lets try to search from this ArrayList :-
System.out.println(employees.contains(e1)); // prints true Employee e3 = new Employee(1, "Rajesh"); System.out.println(employees.contains(e3)); // prints true
The equals method is implemented such that if the ‘id’ and ‘name’ matches, then two Employee objects are considered equals. This time, while searching, equals() method of Employee class is called to check object equality and therefore we get true while searching Employee e3.
What is that hashcode() method there?
It is generally necessary to override the hashCode() method whenever equals() is overridden, so as to maintain the general contract for the hashCode() method, which states that equal objects must have equal hash codes.