What are some of the best practices relating to Java collection?

  1. Use non synchronized Collection: Use ArrayList, HashMap as opposed to Vector, Hashtable etc. Thus we can avoid the synchronization overhead. Even more better is to use an array where possible. If multiple threads are concurrently access a collection and at least one of the threads either adds or deletes an entry into the collection, then the collection must be externally synchronized. This can be achieved by:  
Map aMap = Collections.synchronizedMap (aMap); 
List aList = Collections.synchronizedList (aList);  
  1. Set the initial capacity of a collection appropriately: Set the initial capacity of a collection appropriately (e.g. ArrayList, HashMap etc) whenever possible. As because collection classes like ArrayList, HashMap etc must grow periodically to accommodate new elements. But if you have a very large number of elements to process, and you know the size in advance then you can speed things up by setting the initial size appropriately of the Collection.

    For example: HashMaps/Hashtables needs to be created with sufficiently large capacity to minimize rehashing (which happens every time the table grows). HashMap has two parameters initial capacity and load factor that affect its performance and space requirements. Higher load factor values (default load factor of 0.75 provides a good tradeoff between performance and space) will reduce the space cost but will increase the lookup cost of aMap.get(…) and aMap.put(…) methods. When the number of entries in the HashMap exceeds the (current capacity * loadfactor)  then the capacity of the HashMap is roughly doubled by calling the rehash function. It is also very important not to set the initial capacity too high or load factor too low if iteration performance or reduction in space is important. 

  2. Program in terms of interface not implementation: For example, you might decide a LinkedList is the best choice for some application, but then later decide ArrayList might be a better choice for performance reason.

    // Use:          
    List list = new ArrayList(100);
    
    //program in terms of interface & set the initial capacity. Instead of:           
    ArrayList list = new ArrayList(); 
  3. Use generic type and diamond operator: Earlier we were used to declare a Collection of generic type in the following way:
    List<Student> studentList = new ArrayList<Student>();

    Since Java 7, the compiler can infer the generic type on the right side from the generic type declared on the left side, so you can write:

    List<Student> studentList = new ArrayList<>();

    The <> is informally called the diamond operator. This operator is quite useful. Specially when we use Collection to define some Complex data structure.Consider we are storing result of every student by department. In that case we will use following data structure:

    Map<Department,Map<Student,Result>> studentResultByDepartment=new HashMap<Department,Map<Student,Result>>();

    But using the diamond operator the code is more clean to read.

    Map<Department,Map<Student,Result>> studentResultByDepartment = new HashMap<>();
  4. Prefer isEmpty() over size(): Avoid checking the emptiness of a collection like this:
    if (myList.size() > 0) {
        // do something if the list is not empty  
    }    
    Instead, you should use the isEmpty() method:
    if (!myList.isEmpty()) {
        // do something if the list is not empty
    }

    There’s no performance difference between isEmpty() and size(). The reason is for the readability of the code. More over you can use Apache’s Collection util, which has even more readable methods  : Use org.apache.commons.collections4.CollectionUtils

    // Null-safe check if the specified collection is empty.
    // If Null returns true.
    public static boolean isEmpty(Collection coll)
    
    // Null-safe check if the specified collection is not empty.
    // If Null returns false.
    public static boolean isNotEmpty(Collection coll)
    
  5. Avoid to use the classic for loop: Using classic for loop with Collection will not have any performance impact. But it will decrease the readability of the code and can introduce potential bug in your code. Consider the following example:
    for (int i = 0; i < itemList.size(); i++) {
        Item item = itemList.get(i);
        // do something with item 
    }
    There is nothing wrong with the code. However, this is considered as bad practice because using the counter variable i may lead to potential bugs if it is altered somewhere inside the loop. Also this kind of loop is not object-oriented, since every collection has its own iterator. So it’s recommended to use an iterator like the following code:
    Iterator<Item> iterator = aList.iterator();
     
    while (iterator.hasNext()) {
        Item item = iterator.next();
         // do something with item 
    }
    
    // More over You also can use ListIterator which support both forward and backward iteration
    listItr = aList.listIterator();
    System.out.println("Elements in forward directiton");
    while(listItr.hasNext()){
    	System.out.println(listItr.next());
    }
    System.out.println("Elements in backward directiton");
    while(listItr.hasPrevious()){
    	System.out.println(listItr.previous());
    }
    Also the iterator may throw ConcurrentModificationException if the collection is modified by another thread after the iterator is created, which eliminates potential bugs.
    Now, it’s better to use the enhanced for loop like this:
    for (Item item: itemList) {
        // do something with an item
    }
    As you can see, the enhanced for loop is more succinct and readable though it uses an iterator behind the scenes.
  6. Using Arrays and Collections utility classes: Java Collections Framework provides two utility classes named Arrays and Collections which give us many useful functionalities. For example, the Arrays.asList() method returns a list collection containing the given elements, as you can see I used this method in many examples:
    import java.util.Arrays;
    import java.util.List;
    
    /*
     * A java example source code to demonstrate
     * the use of asList() method of Arrays class
     */
    
    public class ArraysAsListExample {
    
    	public static void main(String[] args) {
    
    		// initialize a new String array
    		String[] studentArray = new String[]{"Ninja Panda","Master Shifu","x-men"};
    		
    		// convert the student database into list
    		List<String> studentList = Arrays.asList(studentArray);
    				
    		// print how many student on the list
    		System.out.println("Count of Students:"+ studentList.size());
    		
    		// print the name of students
    		for(String s : studentList ){
    			System.out.println(s);
    		}
    
    	}
    }

    And the Collections class provides various useful methods for searching, sorting, modifying elements in a collection (almost on lists). Therefore, remember to look at these two utility classes for reusable methods, before looking for other libraries or writing your own code.

  7.  Use Google’s Guava library to Manipulate Collections: Static utility methods pertaining to List instances. Also see this class's counterparts SetsMaps and Queues.

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Lists.html

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Sets.html

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Maps.html

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Queues.html

This libraries will be better for users , who don't have Java 7 as of now:

The guava builder saves typing the type arguments multiple times. Compare:

List<Foo<Bar, Baz>> list = Lists.newArrayList();
List<Foo<Bar, Baz>> list = new ArrayList<Foo<Bar, Baz>>();

In Java 7 it's a bit obsolete though, because you have the diamond operator:

List<Foo<Bar, Baz>> list = new ArrayList<>();

 

core java 12 Collections 12

FOLLOW US ON LinkedIn



Explore Tutu'rself