Friday 8 April 2016

Effective Java Item 30,32,33 fromString(), EnumSet and EnumMap

Correct way to implement enum's fromString. We should always use EnumSet and EnumMap because they are faster than HashMap.


 import java.util.*;  
 enum Operation {  
   PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/");  
   private static final Map<String, Operation> stringToEnum = new HashMap<>();  
   static {  
     for (Operation op : values()){  
       stringToEnum.put(op.toString(), op);  
     }  
   }  
   private String symbol;  
   Operation(String symbol){  
     this.symbol = symbol;  
   }  
   public String toString(){  
     return symbol;  
   }  
   public static Operation fromString(String symbol){  
     return stringToEnum.get(symbol);  
   }  
 }  
 public class EnumSetMap {  
   public static void main(String[] args){  
     Set<Operation> enumSet = EnumSet.of(Operation.PLUS, Operation.MINUS);  
     Map<Operation, String> enumMap = new EnumMap<>(Operation.class);  
     System.out.println(Operation.fromString("+"));  
   }  
 }  

Effective Java Item 30: Strategy enum pattern

 enum PayrollDay {  
   MONDAY(PayType.WEEKDAY),  
   TUESDAY(PayType.WEEKDAY),  
   WEDNESDAY(PayType.WEEKDAY),  
   THURSDAY(PayType.WEEKDAY),  
   FRIDAY(PayType.WEEKDAY),  
   SATURDAY(PayType.WEEKEND),  
   SUNDAY(PayType.WEEKEND);  
   private final PayType payType;  
   PayrollDay(PayType payType){  
     this.payType = payType;  
   }  
   double pay (double hoursWorked, double payRate){  
     return payType.pay(hoursWorked, payRate);  
   }  
   private enum PayType {  
     WEEKDAY {  
       double overtimePay(double hours, double payRate){  
         return hours <= HOURS_PER_SHIFT ? 0 : (hours - HOURS_PER_SHIFT) * payRate / 2;  
       }  
     },  
     WEEKEND {  
       double overtimePay(double hours, double payRate){  
         return hours * payRate / 2;  
       }  
     };  
     private static final int HOURS_PER_SHIFT = 8;  
     abstract double overtimePay(double hours, double payRate);  
     double pay(double hoursWorked, double payRate){  
       double basePay = hoursWorked * payRate;  
       return basePay + overtimePay(hoursWorked, payRate);  
     }  
   }  
 }  
 public class StrategyEnumPattern{  
   public static void main(String[] args){  
     for (PayrollDay payrollDay : PayrollDay.values()){  
       System.out.println(payrollDay + " pays " + payrollDay.pay(9, 100));  
     }  
   }  
 }  

Effective Java Item 28: Generics Comparable

What's the benefit of using Comparable<? super T>?

   public static <T extends Comparable<T>> T max1 (List<T> list){  
     //implementation not import  
     return null;  
   }  
   public static <T extends Comparable<? super T>> T max2 (List<T> list){  
     //implementation not import  
     return null;  
   }  

The code below compiles fine.

 class Cat implements Comparable<Cat>{  
   @Override  
   public int compareTo(Cat o) {return 0;}  
   public static void main(String[] args){  
     List<Cat> cats = new ArrayList<>();  
     max1(cats);  
     max2(cats);  
   }  
 }  
However, if we make Cat extend Animal and allow it to compare with other animals....

 class Animal{}  
 class Cat extends Animal implements Comparable<Animal>{  
   @Override  
   public int compareTo(Animal o) {  
     return 0;  
   }  
 }  

max1() doesn't compile any more. Clearly, Comparable<? super T> is more flexible.