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
- Core Java Coding Questions: Creating a custom hierarchical List in Java -- Part 1: subList with a predicate functionality.
- Core Java Coding Questions: Creating a custom hierarchical List in Java -- Part 2: toString( ) method to print the hierarchy.
- Core Java Coding Questions: Creating a custom hierarchical List in Java -- Part 3: add(...) method to add new items and propagate that to parent and children.
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: Coding

0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home