Google

Jun 7, 2014

Core Java Coding Questions: Creating a custom hierarchical List in Java -- Part 4

Q. Can you write a custom list class that supports following features?

1. Allows you to maintain a parent/child hierarchy of sub lists.
2. Allows you to create sublists from a given list and a predicate (i.e a condition)
3. If you add an item or element to a list, the addition must be propagated to its parent and child lists.
4. If you remove an element from a list, the removal must be propagated to its parent and child lists.

In the previous parts


In this part, you will be adding a remove(...) method to remove an item from the hierarchical list.

Step 1: Remove the UnsupportedOperationException with the following recursive method call. It can be done with iterative calls with a Deque as shown in part 2 for the toString( ) method.

//....removed methods

public class CustomList<E> implements List<E> {

    //...removed constructors & methos  

 
 @SuppressWarnings("unchecked")
 @Override
 //remove the given item
 public boolean remove(Object o) {
  return remove((E)o, null);
 }
 
 @Override
 //remove by index
 public E remove(int index) {
   E item = this.list.get(index);
      return (item != null && remove(item)) ? item : null;
 }
 
 /**
  * remove from the parent and children if the predicate is satisfied
  * protected method
  */

 protected boolean remove(E e, CustomList<E> givenList) {

  // First evaluate whether or not the item is likely to be in this
  // list...
  if (!evaluate(e)) {
   return false;
  }

  boolean hasRemoved = true;

  // if parent exists, remove from the parent
  if (parent != null && parent != givenList) {
   // Recursive method call. The parent takes care of siblings...
   hasRemoved = parent.remove(e, this);
  }

  // if removal fails, return false
  if (!hasRemoved) {
   return false;
  }

  // Remove from this
  if (givenList != this) {
   hasRemoved = this.list.remove(e);
  }

  if (!hasRemoved) {
   if (parent != null) {
    throw new IllegalStateException("Failed to remove !!");
   } else {
    return false;
   }
  }

  // Remove from the sublists
  for (CustomList<E> sublist : sublists) {
   if (sublist != givenList) {
       //recursive call
       sublist.remove(e, this);
   }
  }

  return true;
 }


 private boolean evaluate(E e) {
  return (this.predicate != null) ? this.predicate.evaluate(e) : true;
 }
 
 
 //...removed some methods 

}

Step 2: The CustomListTest class with the main method to run.




package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CustomListTest {

 public static void main(String[] args) {
  /**
   * Arrays.asList returns a List wrapper around an array. This wrapper
   * has a fixed size and is directly backed by the array, and as such
   * calls to set will modify the array, and any other method that
   * modifies the list will throw an UnsupportedOperationException.
   * hence creating a new ArrayList(...) instance
   */
  List<Integer> initialList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

  CustomList<Integer> customList = new CustomList<Integer>(initialList);
  System.out.println("customList: " + customList);

  Predicate<Integer> oddNumberPredicate = new OddNumberPredicate<Integer>();
  CustomList<Integer> oddNumbersSubList = customList.subList(oddNumberPredicate);
  System.out.println("oddNumbersSubList: " + oddNumbersSubList);

  Predicate<Integer> factorOf5Predicate = new FactorOf5Predicate<Integer>();
  CustomList<Integer> factorOf5SubList = customList.subList(factorOf5Predicate);
  System.out.println("factorOf5SubList: " + factorOf5SubList);

  Predicate<Integer> factorOf3Predicate = new FactorOf3Predicate<Integer>();
  CustomList<Integer> factorOf3SubList = oddNumbersSubList.subList(factorOf3Predicate);
  System.out.println("factorOf3SubList : " + factorOf3SubList);

  System.out.println("Demonstrate printing customList again");
  System.out.println("customList : " + customList);

  // add an item or element
  customList.add(11); // this should be added to customList and
       // oddNumbersSubList
  customList.add(15); // this should be added to all four lists.

  System.out.println("After adding 11 & 15: ");
  System.out.println("customList : " + customList);
  
  customList.remove(new Integer(15)); 
  
  System.out.println("After removing 15: ");
  System.out.println("customList : " + customList);

 }

}

The output is:

customList: list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]



oddNumbersSubList: parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

list: [1, 3, 5, 7, 9]



factorOf5SubList: parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

list: [5, 10]



factorOf3SubList : parent: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

parent: [1, 3, 5, 7, 9]

list: [3, 9]



Demonstrate printing customList again

customList : list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

child: [1, 3, 5, 7, 9]

child: [5, 10]

child: [3, 9]



After adding 11 & 15:

customList : list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15]

child: [1, 3, 5, 7, 9, 11, 15]

child: [5, 10, 15]

child: [3, 9, 15]



After removing 15:

customList : list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

child: [1, 3, 5, 7, 9, 11]

child: [5, 10]

child: [3, 9]





Q. What is a composite design pattern?
A. Composite pattern allows creation of a tree structure in which individual nodes are accessed uniformly whether they are leaf nodes or branch (composite) nodes.

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home