Showing posts with label guava tutorial. Show all posts
Showing posts with label guava tutorial. Show all posts

Sunday, January 4, 2015

Google Guava Cache Implementation

Caches are very useful in a range of use cases. for frequent data you can have it in cache instead of doing some computing intensive operation that will help you to achieve a good performance.

you can build a cache using a simple hashmap implementation where you put your data in the key/value pair form. putIfAbsent() method of hashmap is very handy to update the hashmap if lookup for the key fails.

in the multithreaded environment you can suffer a dirty read in case you are using a simple hashmap implementation. for the multithreaded environment you need of focus on the ConcurrentHashMap which will provide you concurrency.

ConcurrentMap based caching is good but you need to adopt a use defined eviction policy to remove element which are not used frequently.
Google guava api provide you more flexible caching based on the ConcurrentMap with more cleaner implementation with a limitation that it not store data in files or on some server e.g. Memcached.Apart from the eviction policy it also support the putIfAbsent scenerio well.

in the coming example lets see how simple is to create and use Guava based cache.
package com.rajkrrsingh.test.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class GuavaCache {
 
  private static final long MAX_SIZE = 100;
 
  private final LoadingCache<String, String> cache;
 
  public GuavaCache() {
    cache = CacheBuilder.newBuilder().maximumSize( MAX_SIZE ).build( new CacheLoader<String, String>() {
        @Override
        public String load( String key ) throws Exception {
          return key.toUpperCase();
        }
      }
    );
  }
 
  public String getEntry( String key ) {
    return cache.getUnchecked( key );
  }
 
  
  public static void main(String[] args) {
 GuavaCache gchache = new GuavaCache();
 System.out.println(gchache.getEntry("hello"));
 System.out.println(gchache.cache.size());
 for (int i = 0; i < 150; i++) {
  System.out.println(gchache.getEntry("hello"+i));
  System.out.println(gchache.cache.size());
 }
 // checking the eviction policy
 System.out.println(gchache.cache.getIfPresent("hello"));
}
}

Google Gauva API in a one glance: Throwables

public final class Throwables
extends Object
Static utility methods pertaining to instances of Throwable.
static List<Throwable>getCausalChain(Throwable throwable)
Gets a Throwable cause chain as a list.
static ThrowablegetRootCause(Throwable throwable)
Returns the innermost cause of throwable.
static StringgetStackTraceAsString(Throwable throwable)
Returns a string containing the result of toString(), followed by the full, recursive stack trace of throwable.
static RuntimeExceptionpropagate(Throwable throwable)
Propagates throwable as-is if it is an instance of RuntimeException or Error, or else as a last resort, wraps it in a RuntimeException then propagates.
static <X extends Throwable>
void
propagateIfInstanceOf(Throwable throwable, Class<X> declaredType)
Propagates throwable exactly as-is, if and only if it is an instance of declaredType.
static voidpropagateIfPossible(Throwable throwable)
Propagates throwable exactly as-is, if and only if it is an instance of RuntimeException or Error.
static <X extends Throwable>
void
propagateIfPossible(Throwable throwable, Class<X> declaredType)
Propagates throwable exactly as-is, if and only if it is an instance of RuntimeException, Error, or declaredType.
static <X1 extends Throwable,X2 extends Throwable>
void
propagateIfPossible(Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2)
Propagates throwable exactly as-is, if and only if it is an instance of RuntimeException, Error, declaredType1, or declaredType2.
let's see how throwables work with the help of sample code
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;

import com.google.common.base.Throwables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaBiMapAndMultiMapDemo {

public static void main(String[] args) throws Exception {
throwablesDemo();
}
// working with throwables
public static void throwablesDemo() throws Exception {

try {
try {
try {
throw new RuntimeException("Root exception");
}
catch(Exception e) {
throw new SQLException("Middle tier exception", e);
}
}
catch(Exception e) {
throw new IllegalStateException("outer exception", e);
}
}
catch(Exception e) {
// getting the root exception
System.out.println(Throwables.getRootCause(e).getMessage());
// list of exceptions
List<Throwable> list = Throwables.getCausalChain(e);
Iterator<Throwable> itr= list.iterator();
while(itr.hasNext()){
System.out.println(itr.next().getMessage());
}
// get stacktrace as string
System.out.println(Throwables.getStackTraceAsString(e));
}
}

}

Google Gauva API in a one glance: BiMap,Multimap

@GwtCompatible
public interface BiMap<K,V>
extends Map<K,V>
A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. This constraint enables bimaps to support an "inverse view", which is another bimap containing the same entries as this bimap but with reversed keys and values.

@GwtCompatible
public interface Multimap<K,V>
A collection that maps keys to values, similar to Map, but in which each key may be associated with multiple values. You can visualize the contents of a multimap either as a map from keys to nonempty collections of values:
  • a → 1, 2
  • b → 3
... or as a single "flattened" collection of key-value pairs:
  • a → 1
  • a → 2
  • b → 3
Important: although the first interpretation resembles how most multimaps are implemented, the design of the Multimap API is based on the second form. So, using the multimap shown above as an example, the size() is 3, not 2, and thevalues() collection is [1, 2, 3], not [[1, 2], [3]]. For those times when the first style is more useful, use the multimap's asMap() view (or create a Map<K, Collection<V>> in the first place).



lets see sample code to understand how BiMap and MultiMap works

/**
* 
*/
package com.rajkrrsingh.test.guava;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Multimap;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaBiMapAndMultiMapDemo {

public static void main(String[] args) {
biMapDemo();
multiMapDemo();
}

// BiMap unique with both keys and value, will throw an exception if try to add a duplicate value
public static void biMapDemo(){
BiMap<String, String> map = HashBiMap.create();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");

//map.put("key4", "value1");
//forceput to put forcefully
map.forcePut("key4", "value1");

// inverse a BiMap
BiMap<String, String> inverseMap = map.inverse();
System.out.println(inverseMap.get("value1"));
}

// MultiMap to substitute object similar to Map<String,List<String>>, do not enforce a list existance before adding an element to the list for given key
public static void multiMapDemo(){
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("key1","value1");
multimap.put("key1","value2");
multimap.put("key1","value3");
multimap.put("key1","value4");
multimap.put("key2","value1");
multimap.put("key2","value2");
multimap.put("key2","value3");
multimap.put("key3","value1");

System.out.println(multimap.get("key1").size());
}

}

Google Gauva API in a one glance: ObjectArrays, Ranges, Stopwatch

ObjectArrays : operate on arrays of any type and allows to concatenate arrays and add single element before first or after last position.
Ranges : Ranges and Range classes are used to define ranges and then checking if a given object is contained within defined range.
Stopwatch : to measure the elapsed time between a operation.
lets test these out using sample code
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import com.google.common.base.Predicate;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Iterables;
import com.google.common.collect.ObjectArrays;
import com.google.common.collect.Range;
import com.google.common.collect.Ranges;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaTestDemo {

public static void main(String[] args) {
objectArrayDemo();
rangesDemo();
stopWatchDemo();
}

// ObjectArrays to operate on array of given type,concanate two arrays, add element on first and last index
public static void objectArrayDemo(){
String[] arr1 = new String[]{"ele1","ele2","ele3"};
String[] arr2 = new String[]{"ele11","ele22"};

String[] conArray = ObjectArrays.concat(arr1, arr2, String.class);
System.out.println(Arrays.toString(conArray));

String[] arr3= ObjectArrays.concat(arr1, "ele4");
System.out.println(Arrays.toString(arr3));

String[] arr4= ObjectArrays.concat("ele00", arr2);
System.out.println(Arrays.toString(arr4));
}

// Ranges to define ranges and then identify element is contained within the range or not
public static void rangesDemo(){
Range<Integer> closedRange = Ranges.closed(1, 10);
System.out.println(closedRange.contains(10));
System.out.println(closedRange.contains(11));

Range<Integer> rightOpenRange = Ranges.closedOpen(1, 10);
System.out.println(rightOpenRange.contains(10));
}

// demonstation of stopwatch
public static void stopWatchDemo(){
final Stopwatch stopwatch = new Stopwatch();
stopwatch.start();

//Sleep for few random milliseconds.
try {
Thread.sleep(new Random().nextInt(1000));
} catch (final InterruptedException interruptedException) {
interruptedException.printStackTrace();
}

stopwatch.stop(); //optional

System.out.println("Elapsed time ==> " + stopwatch);
System.out.println("Elapsed time in Nanoseconds ==> " + stopwatch.elapsedTime(TimeUnit.NANOSECONDS));
System.out.println("Elapsed time in Microseconds ==> " + stopwatch.elapsedTime(TimeUnit.MICROSECONDS));
System.out.println("Elapsed time in Milliseconds ==> " + stopwatch.elapsedTime(TimeUnit.MILLISECONDS));
}

}

Google Gauva API in a one glance: Iterables


@GwtCompatible(emulated=true)
public final class Iterables
extends Object
This class contains static utility methods that operate on or return objects of type Iterable. Except as noted, each method has a corresponding Iterator-based method in the Iterators class.Performance notes: Unless otherwise noted, all of the iterables produced in this class are lazy, which means that their iterators only advance the backing iteration when absolutely necessary.

lets see how iterables work using the following sample code, you can follow the blog entry for Employee class implementation.
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Iterator;
import java.util.List;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaIterablesDemo {

public static void main(String[] args) {
iterablesDemo();
}

// working with iterables
public static void iterablesDemo(){

//all() method allows to check if defined condition is satisfied by all elements from Collection
boolean flag = Iterables.all(Employee.getEmployeeList(), new Predicate<Employee>() {

@Override
public boolean apply(Employee emp) {
return emp.getEmpid().length()==3;
}
});
if(flag){
System.out.println("all emp of empid of length 3");
}else{
System.out.println("not all emp of empid of length 3");
}

// iterate in infinite cycle
int iterateCount=0;
Iterator<Employee> itr = Iterables.cycle(Employee.getEmployeeList()).iterator();
while(itr.hasNext() && iterateCount<20){
System.out.println(itr.next());
iterateCount++;

}

// counts number of elemens in the Collection
int count = Iterables.frequency(Employee.getEmployeeList(), null);
System.out.println(count);

//getFirst
System.out.println(Iterables.getFirst(Employee.getEmployeeList(), new Employee()));

// getLast
System.out.println(Iterables.getLast(Employee.getEmployeeList(), new Employee()));

// partition a list
Iterable<List<Employee>> iterables = Iterables.partition(Employee.getEmployeeList(), 2);
System.out.println(Iterables.size(iterables));

// iterables to array
Employee[] empArr = Iterables.toArray(Employee.getEmployeeList(), Employee.class);
System.out.println(empArr.length);
}
}

Google Gauva API in a one glance: Preconditions and Constraints

allows to check correctness of parameters passed to our method and throw an appropriate exception when necessary.
public final class Preconditions
extends Object
Simple static methods to be called at the start of your own methods to verify correct arguments and state. This allows constructs such as
if (count <= 0) {
       throw new IllegalArgumentException("must be positive: " + count);
     }
to be replaced with the more compact
checkArgument(count > 0, "must be positive: %s", count);
Deprecated. 
Use Preconditions for basic checks. In place of constrained collections, we encourage you to check your preconditions explicitly instead of leaving that work to the collection implementation. For the specific case of rejecting null, consider the immutable collections. This class is scheduled for removal in Guava 16.0.
@Beta
@Deprecated
@GwtCompatible
public final class Constraints
extends Object
Factories and utilities pertaining to the Constraint interface.

let's see how precondition and Constraints works
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.List;

import com.google.common.base.Preconditions;
import com.google.common.collect.Constraint;
import com.google.common.collect.Constraints;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaPreCoditionsDemo {

public static void main(String[] args) {
constrainDemo();
preConditionDemo("rks");
}

// create a constrain on the list which will check when you try to add an element on the list, throw exception in constrained voilation
public static void constrainDemo(){
List<Employee> list = Constraints.constrainedList(Employee.getEmployeeList(), new Constraint<Employee>() {

@Override
public Employee checkElement(Employee emp) {
Preconditions.checkArgument(emp.getAge()>30);
return emp;
}
});
System.out.println(list.size());
// allow to add the element in the list
list.add(new Employee("109", "empName", 10210, 38));
System.out.println(list.size());
}

// validate argument passed to the method and throw required exceptions
public static void preConditionDemo(String arg){
System.out.println(Preconditions.checkNotNull(arg).toUpperCase());
}
}



Google Gauva API in a one glance: Splitter and Strings class

Splitter Class

@GwtCompatible(emulated=true)
public final class Splitter
extends Object
Extracts non-overlapping substrings from an input string, typically by recognizing appearances of a separator sequence. This separator can be specified as a single character, fixed string, regular expression or CharMatcher instance. Or, instead of using a separator at all, a splitter can extract adjacent substrings of a given fixed length.

work opposite to the joiner, Split string into the elements of collection using delimeter which can be sequence of chars,CharMatcher or a regex.
let's see how splitter work using sample code.
/**
 * 
 */
package com.rajkrrsingh.test.guava;

import java.util.Iterator;

import com.google.common.base.Splitter;

/**
 * @author rks
 * @04-Jan-2015
 */
public class GuavaSplitterDemo {

 public static void main(String[] args) {
  splitterDemo();
 }

 // Split a string into a collection of elements
 public static void splitterDemo(){
  Iterator<String> itr = Splitter.on("#").split("RKS#John#Harry#Tom").iterator();
  while(itr.hasNext()){
   System.out.println(itr.next());
  }
  // split on pattern
  Iterator<String> itr1 = Splitter.onPattern("\\d+").split("RKS1John2Harry3Tom").iterator();
  while(itr1.hasNext()){
   System.out.println(itr1.next());
  }
  // omit empty string
  Iterator<String> itr2 = Splitter.on("#").omitEmptyStrings().trimResults().split("RKS# #John#   #Harry#Tom").iterator();
  while(itr2.hasNext()){
   System.out.println(itr2.next());
  }
  // fixed length string extractor
  Iterator<String> itr3 = Splitter.fixedLength(3).split("RKS#John#Harry#Tom").iterator();
  while(itr3.hasNext()){
   System.out.println(itr3.next());
  }
 }
}


Strings Class

@GwtCompatible
public final class Strings
extends Object
Static utility methods pertaining to String or CharSequence instances.

lets see how splitter work using the following sample code.
/**
* 
*/
package com.rajkrrsingh.test.guava;

import com.google.common.base.Strings;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaStringsDemo {

public static void main(String[] args) {
stringHelper();
}

// helper class to String 
public static void stringHelper(){
String str = ""; 
if(Strings.isNullOrEmpty(str)){
System.out.println("String is null or empty");
}
System.out.println(Strings.nullToEmpty(str));
System.out.println(Strings.emptyToNull(Strings.nullToEmpty(str)));
//repeat a string 
System.out.println(Strings.repeat("RKS", 3));
// string padding
System.out.println(Strings.padEnd("RKS", 10, '*'));
System.out.println(Strings.padStart("RKS", 10, '*'));
}
}


Google Gauva API in a one glance: Objects Class to Implement hashcode, equals, toString and compareTo methods

Objects class helps the developer accurately and easily implement the equals(), hashCode(),toString(), and compareTo() methods. it gives the developer to provide implementation of these utility method in more clean and compact way.Developer need not to worry about the clumsy implementation involving variables and nulls.
lets demonstrate it by taking out Employee Class and override these methods with the help of Objects class
package com.rajkrrsingh.test.guava;

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

import com.google.common.base.Objects;
import com.google.common.collect.ComparisonChain;

public class Employee implements Comparable<Employee>{

private String empid;
private String empName;
private int salary;
private int age;
private static List<Employee> list;

static{
list = new ArrayList<Employee>();
list.add(new Employee("101", "RKS", 10000, 31));
list.add(new Employee("102", "Derek", 10500, 35));
list.add(new Employee("103", "Jack", 9000, 29));
list.add(new Employee("104", "Nick", 9600, 35));
}

public  static List<Employee> getEmployeeList(){
return list;
}

public Employee(){}

public Employee(String empid,String empName,int salary,int age){
this.empid = empid;
this.empName = empName;
this.salary = salary;
this.age = age;
}

public String getEmpid() {
return empid;
}

public void setEmpid(String empid) {
this.empid = empid;
}

public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}

public int getSalary() {
return salary;
}

public void setSalary(int salary) {
this.salary = salary;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}


@Override
public int hashCode() {
// TODO Auto-generated method stub
return Objects.hashCode(empid,empName);
}


@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Employee)) {
return false;
}
Employee emp = (Employee) obj;
return Objects.equal(this.empid, emp.empid) && Objects.equal(this.empName, emp.empName); 
}


@Override
public String toString() {
return Objects.toStringHelper(this).add("empid", empid).add("empName", empName).toString();
}


@Override
public int compareTo(Employee o) {
// ComparisionChain 
return ComparisonChain.start().compare(empid, o.empid)
.compare(empName, o.empName)
.compare(salary, o.salary)
.compare(age, o.age)
.result();
}


}
now test our implementation using out tester class
/**
* 
*/
package com.rajkrrsingh.test.guava;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaObjectsDemo {

public static void main(String[] args) {
objectClass();
cleanComapreToTest();
}


// see the compareTo implementation in Employee class
public static void cleanComapreToTest(){
Set<Employee> set = new HashSet<Employee>();
// print true
System.out.println(set.add(new Employee("101", "RKS", 10000, 31)));
// print false - duplicate object
System.out.println(set.add(new Employee("101", "RKS", 10000, 31)));
}

// Object class with the helper method to implement hashcode() equals() and toString() methods
public static void objectClass(){
Employee e = new Employee("105", "Tom", 80000, 24);
// toString test
System.out.println(e);
Employee e1 = new Employee("105", "Tomm", 80000, 24);
System.out.println(e1.equals(e));
}
}

Google Gauva API in a one glance: CharMatcher

It's a class similar to Predicate,apply a boolean check on the chars, have methods to work on the char sequence e.g.
removeFrom(), replaceFrom(), trimFrom(), collapseFrom(), retainFrom()
lets see a simple example involving CharMatcher, follow along the code here
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaCharMatcherDemo {

public static void main(String[] args) {
charMatcher();
}


public static void charMatcher(){
// remove char occurance in the range of 1 and 4
System.out.println(CharMatcher.inRange('1', '4').removeFrom(" 981 654 239"));
// negate the result obtained from previous statement
System.out.println(CharMatcher.inRange('1', '4').negate().removeFrom(" 981 654 239"));
// count no of digit in the string
System.out.println(CharMatcher.DIGIT.countIn(" 981 654 239 "));
// collapse a matching digits with the provided chars
System.out.println(CharMatcher.DIGIT.collapseFrom("collapse from 981 654 239", 'X'));
// replace digit in the string with the provide char
System.out.println(CharMatcher.DIGIT.replaceFrom("collapse from 981 654 239", 'X'));
// trim a string on matching char
System.out.println(CharMatcher.is(' ').trimFrom(" 981 654 239 "));
System.out.println(CharMatcher.is(' ').trimLeadingFrom(" 981 654 239 "));
System.out.println(CharMatcher.is(' ').trimTrailingFrom(" 981 654 239 "));
System.out.println(CharMatcher.is(' ').trimAndCollapseFrom(" 981 654 239 ",'X'));
}
}
Output
 98 65 9
1423
9
collapse from  X X X
collapse from  XXX XXX XXX
981 654 239
981 654 239 
 981 654 239
981X654X239
please follow the comment in the code to relate output.

Google Gauva API in a one glance: Joiner



@GwtCompatible
public class Joiner
extends Object
An object which joins pieces of text (specified as an array, Iterable, varargs or even a Map) with a separator. It either appends the results to an Appendable or returns them as a String.

In the following example, we join a List of String into one String using the “#” as a separator:
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaJoinerDemo {

public static void main(String[] args) {
joinerDemo();
}


// tranform a collection into a sting
public static void joinerDemo(){
List<String> list = Arrays.asList("RKS","John","Nick","Harry");
System.out.println(Joiner.on("#").join(list));

List<String> list1 = Arrays.asList("RKS","John",null,"Nick","Harry");
//skip nulls
System.out.println(Joiner.on("#").skipNulls().join(list1));
//defualt value for null
System.out.println(Joiner.on("#").useForNull("BLANK").join(list1));

// joiner on Map
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");

System.out.println(Joiner.on("#").withKeyValueSeparator(":").join(map));
}
}
Please follow my comments in the code to relate with the output
RKS#John#Nick#Harry
RKS#John#Nick#Harry
RKS#John#BLANK#Nick#Harry
key4:value4#key3:value3#key2:value2#key1:value1

Google Gauva API in a one glance: Predicate

  • Predicate<T>, which has the single method boolean apply(T input). Instances of Predicate are generally expected to be side-effect-free and consistent with equals.

@GwtCompatible
public interface Predicate<T>
Determines a true or false value for a given input.The Predicates class provides common predicates and related utilities.
lets see how to use predicate to filter out some elements from the given collection. create a tester class as follows and follow along my blog post to get Employee Class
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaPredicateDemo {

public static void main(String[] args) {
pridcateDemo();
}

public static void pridcateDemo(){
List<Employee> empList = Employee.getEmployeeList();

Predicate<Employee> ageOver30 = new Predicate<Employee>() {

@Override
public boolean apply(Employee emp) {
if(emp.getAge()>30){
return true;
}
return false;
}
};

Predicate<Employee> slryLt10000 = new Predicate<Employee>() {

@Override
public boolean apply(Employee emp) {
if(emp.getSalary()<10000)
return true;
return false;
}
};

System.out.println("**** print emp name whose age is greater than 30 ****");
Iterator<Employee> filterAgeIterator= Iterables.filter(empList, ageOver30).iterator();
while(filterAgeIterator.hasNext()){
System.out.println(filterAgeIterator.next().getEmpName());
}

System.out.println("**** print emp name whose age is greater than 30 and salary is less than 10000 ****");
Iterator<Employee> filterOnAgeAndSal= Iterables.filter(empList, Predicates.and(ageOver30, slryLt10000)).iterator();
while(filterOnAgeAndSal.hasNext()){
System.out.println(filterOnAgeAndSal.next().getEmpName());
}

System.out.println("**** print emp name whose age is greater than 30 OR salary is less than 10000 ****");
Iterator<Employee> filterOnAgeORSal= Iterables.filter(empList, Predicates.or(ageOver30, slryLt10000)).iterator();
while(filterOnAgeORSal.hasNext()){
System.out.println(filterOnAgeORSal.next().getEmpName());
}
}
}
Please follow my comments in the code to relate with the output
**** print emp name whose age is greater than 30 ****
RKS
Derek
Nick
**** print emp name whose age is greater than 30 and salary is less than 10000 ****
Nick
**** print emp name whose age is greater than 30 OR salary is less than 10000 ****
RKS
Derek
Jack
Nick


Google Gauva API in a one glance: Composite Function


Guava API provide a way to apply series of functions on the given collection using Functions.compose

public static <A,B,C> Function<A,C> compose(Function<B,C> g,
                                            Function<A,? extends B> f)
Returns the composition of two functions. For f: A->B and g: B->C, composition is defined as the function h such that h(a) == g(f(a)) for each a.
Parameters:
g - the second function to apply
f - the first function to apply
Returns:
the composition of f and g

to test it further please follow my blog entry and add one method to the GuavaFunctionDemo class and run it
/**
*
*/
package com.rajkrrsingh.test.guava;

import java.util.Collection;
import java.util.Iterator;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.Collections2;

/**
* @author rks
* @04-Jan-2015
*/
public class GuavaFunctionDemo {

public static void main(String[] args) {
//printEmployeeInUpperCase();
printResultofCompositeFunction();
}

// Transformation of one collection to the other collection using Guava function
public static void printEmployeeInUpperCase(){
Collection<String> upperCaseEmpName = Collections2.transform(Employee.getEmployeeList(),new Function<Employee, String>() {

@Override
public String apply(Employee emp) {
if(emp != null)
return emp.getEmpName().toUpperCase();
return "";

}
});

Iterator<String> itr = upperCaseEmpName.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}

// Apply a series of transformation by compostion of function
public static void printResultofCompositeFunction(){
Function<Employee, String> upperCaseEmpName = new Function<Employee, String>() {

@Override
public String apply(Employee emp) {
if(emp!=null)
return emp.getEmpName().toUpperCase();
return "";
}
};

Function<String, String> reverseEmpName = new Function<String, String>() {

@Override
public String apply(String empName) {
if (empName!=null) {
return new StringBuilder(empName).reverse().toString();
}
return "";
}

};
;
Collection<String> upperReverseCollection = Collections2.transform(Employee.getEmployeeList(), Functions.compose(reverseEmpName, upperCaseEmpName));

Iterator<String> itr = upperReverseCollection.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}

}

you can see here we have applied two function here, the first on is to change element of the collection in uppercase and then reverse it.

Result:
SKR
KERED
KCAJ
KCIN




Saturday, January 3, 2015

Google Gauva API in a one glance: Function

Google Guava Libraries are a nice set of Java utility classes that will probably come in handy in any project. Stuff like immutable collections, string manipulation, handling primitives and easier I/O are some of the concepts they deal with.


  • Function<A, B>, which has the single method B apply(A input). Instances of Function are generally expected to be referentially transparent -- no side effects -- and to be consistent with equals, that is, a.equals(b) implies thatfunction.apply(a).equals(function.apply(b)).

In this tutorial I will demonstarte you how to transform a collection using the function.
package com.rajkrrsingh.test.guava;

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

import com.google.common.base.Objects;
import com.google.common.collect.ComparisonChain;

public class Employee implements Comparable<Employee>{

private String empid;
private String empName;
private int salary;
private int age;
private static List<Employee> list;

static{
list = new ArrayList<Employee>();
list.add(new Employee("101", "RKS", 10000, 31));
list.add(new Employee("102", "Derek", 10500, 35));
list.add(new Employee("103", "Jack", 9000, 29));
list.add(new Employee("104", "Nick", 9600, 35));
}

public static List<Employee> getEmployeeList(){
return list;
}

public Employee(){}

public Employee(String empid,String empName,int salary,int age){
this.empid = empid;
this.empName = empName;
this.salary = salary;
this.age = age;
}

public String getEmpid() {
return empid;
}

public void setEmpid(String empid) {
this.empid = empid;
}

public String getEmpName() {
return empName;
}

public void setEmpName(String empName) {
this.empName = empName;
}

public int getSalary() {
return salary;
}

public void setSalary(int salary) {
this.salary = salary;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}


@Override
public int hashCode() {
// TODO Auto-generated method stub
return Objects.hashCode(empid,empName);
}


@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Employee)) {
return false;
}
Employee emp = (Employee) obj;
return Objects.equal(this.empid, emp.empid) && Objects.equal(this.empName, emp.empName);
}


@Override
public String toString() {
return Objects.toStringHelper(this).add("empid", empid).add("empName", empName).toString();
}


@Override
public int compareTo(Employee o) {
// ComparisionChain
return ComparisonChain.start().compare(empid, o.empid)
.compare(empName, o.empName)
.compare(salary, o.salary)
.compare(age, o.age)
.result();
}


}

Collection2 is the utility class provided by the Gauva API which has transfrom() method with input collection and function implementation and return the transofrmed collection.

/**
 * 
 */
package com.rajkrrsingh.test.guava;

import java.util.Collection;
import java.util.Iterator;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;

/**
 * @author rks
 * @04-Jan-2015
 */
public class GuavaFunctionDemo {

	public static void main(String[] args) {
		printEmployeeInUpperCase();
	}

	// Transformation of one collection to the other collection using Guava function
	public static void printEmployeeInUpperCase(){
		Collection<String> upperCaseEmpName = Collections2.transform(Employee.getEmployeeList(),new Function<Employee, String>() {

			@Override
			public String apply(Employee emp) {
				if(emp != null)
					return emp.getEmpName().toUpperCase();
				return "";

			}
		});

		Iterator<String> itr = upperCaseEmpName.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
		}
	}

}

after running the class you will find all your collection element are in the uppercase.
RKS
DEREK
JACK
NICK