Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Wednesday, July 16, 2014

Don't return in a closure for each() in Groovy

I am a Java coder.  All these years I heard so many buzz about functional language, but I never took the dive.  Well, I got some tastes recently. 

We recently switched to use Gradle to manage the project.  I was banning my head for a couple hours yesterday for an odd problem.


boolean isStartedWithList(String str){
  def list=['pre','post']
  list.each {
    if (str.startsWith(it)){
       println 'hit true'
       return true
    }
   }
  println 'hit default false'
  return false
  }  
If you run isStartedWithList('prehistorical'), you will see
hit true
hit default false
The returned value is false. This is because the (first and the second) return only gets you out of the closure, not the method. There are two ways to fix it: to switch back to the traditional for loop, or not to rely on the early exit from the return call.
boolean isStartedWithList(String str){
  def list=['pre','post']
  for (it:list) {
    if (str.startsWith(it)){
       println 'hit true'
       return true
    }
  println 'hit false'
  return false
  }  
boolean isStartedWithList(String str){
  def list=['pre','post']
  result=false;
  list.each {
    result=result||str.startsWtih(it)
   }
  return result
  }  
Both will get you the expected answer. Lessons are learned!

Edit 7/18/2014:

I just learned a even better one using the groovy collection method any
boolean isStartedWithList(String str){
  return ['pre','post'].any{str.startsWith(it)}
}

Sunday, June 3, 2012

A combiner works in a reducer as well as a mapper

In Hadoop, a combiner is usually introduced as a way to collapse the output record of maps in the end of a map task and therefore reduce the network traffic and alleviate the load of reducers. A less known function of a combiner that I recently discovered is that  it also works in the reduce phase. (CDH3u3, 0.20.2).  A reducer task, more specifically, its shuffle functions,  usually kicks off before all maps finish.  Once it collects enough records from all maps tasks (controlled by "mapred.inmem.merge.threshold" property) through network, records will be merged and a combiner will be called upon those records if one is specified in the job conf.  This is a very useful feature in the case where there are too many map tasks for the system to start them simultaneously.  Map outputs are collapsed by the combiner in the reducer task during the time, and final reduce run will not need to work no more records than "mapred.inmem.merge.threshold".  Many commercial or third-part versions of Hadoop actually specifically advertise some function similar as "proactive execution" or so.  It is great to know that the plain vanilla Hadoop already has something like this.

Thursday, July 1, 2010

Java enum

Java 5 enum is nice, but it is not terribly well documented. The useful information is scattered around. I did a careful study maybe 2 years ago but I am a bit loss when I try to look around for its information now. So maybe it is better to document everything I need here for later reference.


A few useful links:
Type-Safe Enumerations
Using the built-in enumeration methods: values( )
Sun's Tutorial
Spring MVC form tags for enum

Saturday, June 26, 2010

Command Pattern and Generics in Java - JSON Story (3)

So what I want to do is to put a list of the same objects into List<Map<String,String>>. I created some converters for convert single object into <Map<String,String>>;. When I start to write the list converter, I realize that I only need a generic one and use the command pattern.
Here is the list converter:


public class ConverterToList<T> {



public List<Map<String,String>> convertToList(Collection<T> collection, ConverterToMap<T> converter){

List<Map<String,String>> list=new ArrayList<Map<String,String>>();
for (T t:collection){
list.add(converter.convertToMap(t));
}
return list;
}

}

And the interface for command


public interface ConverterToMap<T> {

public Map<String,String> convertToMap(T t);

}

A sample implementation

public class ConverterToMapJob implements ConverterToMap<Job> {

@Override
public Map<String, String> convertToMap(Job job) {
Map<String, String> map = new HashMap<String, String>();

JsonHelper helper = new JsonHelper(map);

helper.addCheckNull(job.getId(), "id");

helper.addCheckNull(job.getSubmitTimestamp(), "submitTimestamp");
helper.addCheckNull(job.getScheduleTimestamp(), "scheduleTimestamp");
helper.addCheckNull(job.getEndTimestamp(), "endTimestamp");
helper.addCheckNull(job.getUpdateTimestamp(), "updateTimestamp");
helper.addCheckNull(job.getHost(), "host");
helper.addCheckNull(job.getName(), "name");
helper.addCheckNull(job.getPort(), "port");
//now I am free to put any bean. Even not a bean.
helper.addCheckNull(job.getJobStatus(), "status");
return map;
}

}


I am fairly happy with this. This structure only handles a flat object or an array of it, and not general enough for more complex multi-level objects. But that fits my needs now and in the foreesable future of this project. I probably will hang with it and leave the json problem in my back. It is generally not a good idea to reinvent the wheel, but when the wheel is too complicated for your car, maybe it is better to roll your own.