Sunday, 1 November 2015

Design a Task Executor for a Car Workshop


Interview question asked in Triple Point Technology Company.

The Car workshop has following Employees on the payroll:
Employee Name
Designation
Joe
Trainee
Smith
Expert
Walker
Employee

Following tasks/duties are performed in the workshop:
Task Name
Service Fee($)
Time Taken(Hours)
Car-Wash
100
2
Car-Repair
1000
5
Car-Paint
1100
4

On any given day, a schedule is created in the morning, in which task/tasks are assigned to each Employee. Example, schedule of 2-Jan-2015:
Employee Name
Task Name
Joe
Car-Wash
Car-Repair
Car-Paint
Smith
Car-Repair
Walker
Car-Paint
Car-Repair

Assignment:  
1.  Design and implement Task, Employee and Schedule classes.
2.  Design and Implement Executor which will schedule and execute tasks of all employees 
3.  All Employees will start their work in Parallel (multi-threaded). 
4.  There can be 2 strategies of Task Prioritization –
       Tasks can be prioritized based on the time taken. More time consuming task should be executed prior to other lesser time-consuming tasks assigned to that employee.
Expected output
Employee Name
Task Name
Time taken
Fee
Joe
Car-Repair
5
1000
Car-Paint
4
1100
Car-Wash
2
100
Smith
Car-Repair
5
1000
Walker
Car-Repair
5
1000
Car-Paint
4
1100

       Tasks can be prioritized based on Service Fee. A Task which charges more service fee should be executed first. Expected output
Employee Name
Task Name
Time taken
Fee
Joe
Car-Paint 
4
1100
Car-Repair
5
1000
Car-Wash
2
100
Smith
Car-Repair
5
1000
Walker
Car-Paint
4
1100
Car-Repair
5
1000

Solution:-
First create bean class for Employee which consist of two variable name and designation.

 /**  
  * @author Dixit  
  *  
  */  
 public class Employee {  
      private String name;  
      private String designation;  
      public Employee(String name,String designation) {  
           this.name=name;  
           this.designation=designation;  
      }  
      /**  
       * @return the name  
       */  
      public String getName() {  
           return name;  
      }  
      /**  
       * @param name the name to set  
       */  
      public void setName(String name) {  
           this.name = name;  
      }  
      /**  
       * @return the designation  
       */  
      public String getDesignation() {  
           return designation;  
      }  
      /**  
       * @param designation the designation to set  
       */  
      public void setDesignation(String designation) {  
           this.designation = designation;  
      }  
 }  


then create bean class for Task consisting of 3 fields taskName,fees,timeTaken.

 /**  
  * @author Dixit  
  *   
  */  
 public class Task {  
      private String taskName;  
      private int fees;  
      private int timeTaken;  
      public Task(String taskName, int fees, int timeTaken) {  
           this.taskName = taskName;  
           this.fees = fees;  
           this.timeTaken = timeTaken;  
      }  
      /**  
       * @return the taskName  
       */  
      public String getTaskName() {  
           return taskName;  
      }  
      /**  
       * @param taskName  
       *      the taskName to set  
       */  
      public void setTaskName(String taskName) {  
           this.taskName = taskName;  
      }  
      /**  
       * @return the fees  
       */  
      public int getFees() {  
           return fees;  
      }  
      /**  
       * @param fees  
       *      the fees to set  
       */  
      public void setFees(int fees) {  
           this.fees = fees;  
      }  
      /**  
       * @return the timeTaken  
       */  
      public int getTimeTaken() {  
           return timeTaken;  
      }  
      /**  
       * @param timeTaken  
       *      the timeTaken to set  
       */  
      public void setTimeTaken(int timeTaken) {  
           this.timeTaken = timeTaken;  
      }  
 }  

create a ScheduleTask class consisting of Employee object and List of Task objects.ScheduleTask implements runnable interface to perform multi threading operation.

 import java.util.List;  
 /**  
  * @author Dixit  
  *   
  */  
 public class ScheduleTask implements Runnable {  
      private Employee e;  
      private List<Task> t;  
      /**  
       * @param e  
       * @param t  
       */  
      public ScheduleTask(Employee e, List<Task> t) {  
           super();  
           this.e = e;  
           this.t = t;  
      }  
      /**  
       * @return the e  
       */  
      public Employee getE() {  
           return e;  
      }  
      /**  
       * @param e  
       *      the e to set  
       */  
      public void setE(Employee e) {  
           this.e = e;  
      }  
      /**  
       * @return the t  
       */  
      public List<Task> getT() {  
           return t;  
      }  
      /**  
       * @param t  
       *      the t to set  
       */  
      public void setT(List<Task> t) {  
           this.t = t;  
      }  
      @Override  
      public void run() {  
           for(Task task:t)  
           {  
                System.out.println("Employee Name: "+e.getName()+" ,Task name: "+task.getTaskName()+" ,Time Taken: "+task.getTimeTaken()+" ,Fee: "+task.getFees());  
           }  
      }   
 }


As we have to prioritize the task based on Time Taken and Service fees.Create a comparator class for each type.

Comparator class for Time Taken by the task:-

 import java.util.Comparator;  
 /**  
  *   
  */  
 /**  
  * Compares the tasks and return task with high value of time taken.  
  * @author Dixit  
  *   
  */  
 public class TaskTimeComparator implements Comparator<Task> {  
      @Override  
      public int compare(Task o1, Task o2) {  
           return o2.getTimeTaken() - o1.getTimeTaken();  
      }  
 }  

Comparator class for Time Taken by the task:-

 import java.util.Comparator;  
 /**  
  * Compares the tasks and return task with high fees.  
  * @author Dixit  
  *  
  */  
 public class TaskFeeComparator implements Comparator<Task> {  
      @Override  
      public int compare(Task o1, Task o2) {  
           return o2.getFees() - o1.getFees();  
      }  
 }  

Now Create a main class which uses executor service framework to start the work in parallel(multi-threading)

 import java.util.ArrayList;  
 import java.util.Collections;  
 import java.util.List;  
 import java.util.concurrent.ExecutorService;  
 import java.util.concurrent.Executors;  
 /**  
  * @author Dixit  
  *   
  */  
 public class ExecutorServiceExample {  
      /**  
       * @param args  
       */  
      public static void main(String[] args) {  
           // creating Employee Object  
           Employee e1 = new Employee("Joe", "Trainee");  
           Employee e2 = new Employee("Smith", "Expert");  
           Employee e3 = new Employee("Walker", "Employee");  
           // Creating Task Object  
           Task t1 = new Task("Car-Wash", 100, 2);  
           Task t2 = new Task("Car-Repair", 1000, 5);  
           Task t3 = new Task("Car-Paint", 1100, 4);  
           //Creating list of task for employee Joe ie e1 object  
           List<Task> l1 = new ArrayList<Task>();  
           l1.add(t1);  
           l1.add(t2);  
           l1.add(t3);  
           //Creating list of task for employee Smith ie e2 object  
           List<Task> l2 = new ArrayList<Task>();  
           l2.add(t2);  
           //Creating list of task for employee Walker ie e3 object  
           List<Task> l3 = new ArrayList<Task>();  
           l3.add(t3);  
           l3.add(t2);  
           System.out.println("Task Prioritization based on time taken:-");  
           // sort the list of task based on time taken  
           Collections.sort(l1, new TaskTimeComparator());  
           Collections.sort(l2, new TaskTimeComparator());  
           Collections.sort(l3, new TaskTimeComparator());  
           // create scheduleTask objects  
           ScheduleTask s1 = new ScheduleTask(e1, l1);  
           ScheduleTask s2 = new ScheduleTask(e2, l2);  
           ScheduleTask s3 = new ScheduleTask(e3, l3);  
     //creating executor service of 3 threads to execute 3 tasks simultaneously  
           ExecutorService executorService = executorService = Executors.newFixedThreadPool(3);  
           // submit the scheduleTask  
           executorService.submit(s1);  
           executorService.submit(s2);  
           executorService.submit(s3);  
           try {  
                Thread.sleep(1000);  
           } catch (InterruptedException e) {  
                System.out.println("Exception:"+e.getMessage());  
           }  
           System.out.println("\nTask Prioritization based on Service Fees:-");  
           // sort the list of task based on fees  
           Collections.sort(l1, new TaskFeeComparator());  
           Collections.sort(l2, new TaskFeeComparator());  
           Collections.sort(l3, new TaskFeeComparator());  
           // create scheduleTask objects  
           ScheduleTask s4 = new ScheduleTask(e1, l1);  
           ScheduleTask s5 = new ScheduleTask(e2, l2);  
           ScheduleTask s6 = new ScheduleTask(e3, l3);  
           // submit the scheduleTask  
           executorService.submit(s4);  
           executorService.submit(s5);  
           executorService.submit(s6);  
           //shutdown executor service  
           while (!executorService.isTerminated()) {  
                executorService.shutdown();  
           }  
      }  
 }  


 Output  
 Task Prioritization based on time taken:-  
 Employee Name: Joe ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  
 Employee Name: Smith ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  
 Employee Name: Walker ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  
 Employee Name: Joe ,Task name: Car-Paint ,Time Taken: 4 ,Fee: 1100  
 Employee Name: Joe ,Task name: Car-Wash ,Time Taken: 2 ,Fee: 100  
 Employee Name: Walker ,Task name: Car-Paint ,Time Taken: 4 ,Fee: 1100  
 Task Prioritization based on Service Fees:-  
 Employee Name: Joe ,Task name: Car-Paint ,Time Taken: 4 ,Fee: 1100  
 Employee Name: Joe ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  
 Employee Name: Joe ,Task name: Car-Wash ,Time Taken: 2 ,Fee: 100  
 Employee Name: Smith ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  
 Employee Name: Walker ,Task name: Car-Paint ,Time Taken: 4 ,Fee: 1100  
 Employee Name: Walker ,Task name: Car-Repair ,Time Taken: 5 ,Fee: 1000  

All the Best :)
In case of any doubt,please post in comment.

How to create a TresSet



The TreeSet class provides four constructors broken into two sets.The first two constructors creates empty trees sets:


    public TreeSet()  
    public TreeSet(Comparator comp)  


In order to maintain an ordering, elements added to a tree set must provide some way for the tree to order them. If the elements implement the Comparable interface, the first constructor is sufficient. If, however, the objects aren’t comparable or you don’t like the default ordering provided, you can pass along a custom Comparator to the constructor that will be used to keep elements ordered. Once the TreeSet is created, you cannot change the comparator.

Note:  As HashSet relying on a internal structure of HashMap, the TreeSet relies on a TreeMap internally.

The other two constructors are copy constructors, copying all elements from one collection into another:


    public TreeSet (Collection c)  
    public TreeSet (SortedSet set)  

If the other collection is a SortedSet, the TreeSet is able to perform some optimizations while adding elements. It also retains the original set’s comparator.



Happy Learning.

How to check if HashSet contains an element or not



In order to find out how many elements are in set, you can use the size() method:

 public int size()  

You can also use isEmpty() method to check if there is any element in given HashSet.


 public boolean isEmpty()   


Sample Program:

 import java.util.HashSet;  
 import java.util.Set;  
 /**  
  *   
  */  
 /**  
  * @author Dixit  
  *   
  */  
 public class HashSetSize {  
      /**  
       * @param args  
       */  
      public static void main(String[] args) {  
           Set set = new HashSet();  
           System.out.println("Before adding element");  
           System.out.println(set.size());  
           System.out.println(set.isEmpty());  
           set.add("a");  
           set.add("b");  
           System.out.println("After adding element");  
           System.out.println(set.size());  
           System.out.println(set.isEmpty());  
      }  
 }  


Output:  
 Before adding element  
 0  
 true  
 After adding element  
 2  
 false  


Happy Reading :)

How to add elements in HashSet



When you need to add elements to a set, you can either add a single element or a group of elements.
              
             1)      Adding Single elements

To add a single element, you can call the add() method:

   public boolean add (Object element)  

The add() method takes a single argument of the element to add. If the element is not in the set, it is added and true is returned. If the element happens to be in the set already, because element.equals(oldElement) returns true, then the new element replaces the old element in the collection and false is returned. If the old element has no other references, it becomes eligible for garbage collection.

If the set is read only, then adding an element will throw UnsupportedOperationException.

Note:- If you need to modify an element in a set, you should remove it, modify it and then re-add it. If you don’t, you can consider the object lost as there is no way of finding the object without manually traversing through all the elements. The is true because change affects the results of hashcode().

              2)      Adding Another Collection

You can add a group of elements from another collection to the set with the addAll() method:

    public boolean addAll (Collection c)  

element in the collection passed in will be added to current set via the subsequent call to add() method on each element. If the underlying set changes, true is returned. If no elements are added, false is returned. As with add(), if equal elements are in both sets, true is returned with the new elements replacing the old elements in the set.

If set is read-only , then it will throw UnsupportedOperationException.


Happy LearningJ

How to create a HashSet



The HashSet classes provides four constructors .The first three constructors crate empty sets of varying sizes:

   public HashSet ()  
   public HashSet (int initialCapacity)  
   public HashSet (int initialCapacity, int loadFactor)  

If initialCapacity is not specified, then initial set size for storing elements will be the default size of a HashMap, which is either 11 or 101 depending upon the Java version you are using. When the set capacity reaches full and a new element is added, the internal structure will double in size before adding the new element. you can also provide custom load factor in the constructor.

The fourth constructor acts as a copy constructor ,copying the elements from ine set into the newly created set:

   public HashSet (Collection c)  

You cannot provide a custom initial capacity or load factor. Instead, the internal map will be sized at twice the size of collection, or eleven if the collection is small(five or less elements),keeping the default load factor of 75%.

Note: If the original collection had duplicates ,only one of the duplicates will be in the final created set.

An easy way to initialize a set without manually adding each element is to create an array of the elements, create a List from that array with Arrays.asList(), then call this constructor with the list as the collection:

  String st[]={“a”,”b”,”c”,”d”,”e”};  
  Set set =new HashSet(Arrays.asList(str));  


Happy Learning J

How to create an ArrayList



There are 3 constructors to create an ArrayList. For the first two construtors, an empty array list is created. The initial capacity is 10 unless it is explicitly specified by using the second constructor. When that space becomes too small, the list will increase by half of its size.

    public ArrayList()  
    public ArrayList (int initialCapacity)  

Note:- Unlike Vector, you cannot specify a capacity increment. For Sun’s reference implementation, the formula to increase capacity is newCapacity=(oldCapacity*3)/2+1. If you happen to call the constructor with a negative initial capacity, an IllegalArgumentException will be thrown.
Another constructor is copy constructor, creating a new ArrayList from another collection:
    
  public ArrayList(Collection c)  

You can not provide a custom initial capacity .Instead, the internal array will be sized at 10% larger than the collection size.

One of the easy way of creating ArrayList is

 String str[] = {“a”,”b”,”c”,”d”,”e”};  
 List list=new ArrayList(Arrays.as List(str));  



Happy Learning J

How to fetch elements from HashSet



To fetch an elements of Hashset, you can call the iterator() method to get an Iterator:
    
   public Iterator iterator()  

Since the elements of hash set are unordered, the order of the elements returned has nothing to do with the order in which they were inserted or added. And as the capacity of the hash set changes, the elements may be reordered.

For example:-

 import java.util.Arrays;  
 import java.util.HashSet;  
 import java.util.Iterator;  
 import java.util.Set;  
 /**  
  *   
  */  
 /**  
  * @author Dixit  
  *   
  */  
 public class HashSetIteration {  
      /**  
       * @param args  
       */  
      public static void main(String[] args) {  
           String str[] = { "a", "b", "c", "d", "e" };  
           Set<String> set = new HashSet<String>(Arrays.asList(str));  
           Iterator<String> itr = set.iterator();  
           while (itr.hasNext()) {  
                System.out.println(itr.next());  
           }  
      }  
 }  

 Output:  
 d  
 e  
 b  
 c  
 a  

Remember that order doesn’t matter as long as each element in the set is displayed.


Happy Reading .