Showing posts with label example. Show all posts
Showing posts with label example. Show all posts

Monday, June 10, 2013

Guava - simple recipes to make your Java code cleaner, 1st part

It isn't article for peoples knowing Guava. It is set of simple examples to encourage to use Guava Library in your code.

#1. You can use Optional instead of simply returning null in some specific cases:

Insted of:
     /**  
     * Can return null in specific cases... but it's
     * hard to remember
     */
    public static String someMethod() {
        String returnValue = null;
        if (new Date().getTime() % 2 == 0) {
            returnValue = "time % 2 == 0";
        }
        return returnValue;
    }

    public static void main(String[] args) {
        String str = someMethod();
        str.contains("%") // will crash
    }
use this:
    /**
     * Explicite shows, that method can
     * return empty (null) value
     */
    public static Optional< String > someMethod() {
        Optional< String > returnValue = Optional.absent();
        if (new Date().getTime() % 2 == 0) {
            returnValue = Optional.of(new String());
        }
        return returnValue;
    }

    public static void main(String[] args) {
        Optional< String > str  = someMethod();
        if(str.isPresent()) {
            // here you know that value is not null
        }
        // or you can operate on given value or a default one
        str.or("default value").contains("%");
    }

#2 You can use firstNonNull from Guavas Objects class insted of write "if else"

Insted of:
    public T foo() {
        ...
        ...
        if(first != null) {
            return first;
        } else {
            return second;
        }
    }
use this:
import static com.google.common.base.Objects.firstNonNull;
...
    public T foo() {
        ...
        ...
        return firstNonNull(first, second);
    }

#3 You can use Guava Strings class methods to deal with null or empty Strings

Insted of:
if(str == null) {
    str = "";
}

if("".equals(str)) {
    str = null;
}

if(str == null || str.length() == 0) {
   // is null or empty
}
use this:
import static com.google.common.base.Strings.*;

str = nullToEmpty(str);
str = emptyToNull(str);
if(isNullOrEmpty(str)) {
   // is null or empty
}

#4 You can use Object.equals(a, b) to check equality safely

Insted of:
a.equals(b); // will crash if a is null
use this:
import static com.google.common.base.Objects.equal;
...
equal(a, null); // return false
equal(null, null); // return true
equal(a, b); // return true if a is equal b

#5 You can use Joiner to join Strings

Insted of:
StringBuffer buffer = new StringBuffer();
for (String str : strs) {
    if (str != null) {
        buffer.append(str);
        buffer.append(", ");
    }
}
if (buffer.length() >= 2) {
    buffer.substring(0, buffer.length() - 2);
}
return buffer.toString();
use this:
import com.google.common.base.Joiner;
...
return Joiner.on(", ").skipNulls().join(strs);

#6 You can use Splitter to split String

Insted of:
String str = "abc, bcd,, cde   ,zsa";
String[] split = str.split(",");

// What with trimming? Whitespaces? Empty strings???
use this:
import com.google.common.base.Splitter;
...
Splitter.on(',')
       .trimResults()
       .omitEmptyStrings()
       .split("abc, bcd,, cde   ,zsa");

#7 You can use Multiset to count object occurences

Insted of:
Map< String, Integer > countMap = new HashMap< String, Integer >();
for (String word : words) {
    if(!countMap.containsKey(word)) {
        countMap.put(word, 0);
    }
    countMap.put(word, countMap.get(word) + 1);
}
use this:
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
...
Multiset< String > wordsMultiset = HashMultiset.create();
wordsMultiset.addAll(words);

#8 You can use Multimap insted of map with List or Set as values

Insted of:
Map< String, List< String > > languagesMap = new HashMap< String, List< String >>();
for (Programmer programmer : programmers) {
    if (languagesMap.get(programmer.getLanguage()) != null) {
        languagesMap.put(programmer.getLanguage(), new ArrayList< String >());
    }
    languagesMap.get(programmer.getLanguage()).add(programmer.getEmail());
}
use this:
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
...
Multimap< String, String > languagesMap = HashMultimap.create();
for (Programmer programmer : programmers) {
    languagesMap.put(programmer.getLanguage(), programmer.getEmail());
}

...next simple, but usable examples soon...

Wednesday, April 10, 2013

Passing arguments by value or by name? What's difference?

In Scala there are two ways to pass values to function. You can pass it by name or value. I try to explain and show examples depicting this issue by write equivalent java code. Let's see example class writen in Scala:
class Example {
  var invocationCount = 0

  def byValue(arg: String) = {
    println(arg)
    println(arg)
    println(arg)
  }

  def byName(arg: => String) = {
    println(arg)
    println(arg)
    println(arg)
  }


  def getMessage(): String = {
    invocationCount += 1
    "invocation count: " + invocationCount
  }
}


object Main {
  def main(args: Array[String]) {

    val example = new Example
    println(example.byValue(example.getMessage()))
    println(example.byName(example.getMessage()))
  }
}
... and output:
invocation count: 1
invocation count: 1
invocation count: 1
()
invocation count: 2
invocation count: 3
invocation count: 4
()
As seen in the first case (method byValue), the method getMessage was evaluated only one time, it result was passed to method byValue and then written three times on screen. And in second case it's a little bit different. In simple terms, when arg was passed by name it is look like passing function as a argument like in JavaScript or like a clousure in Groovy. What about do that in Java? Unfortunately it is not possible to do it in such an elegant and readable way in Java, but is possible to simulate. You can do that by using interface. Let's see Java solution:

// IFunction.java
public interface IFunction< T > {

    T call();
}

// Example.java
public class Example {

    private int invocationCount;

    public void byValue(String arg) {
        System.out.println(arg);
        System.out.println(arg);
        System.out.println(arg);
    }

    public void byName(IFunction< String > function) {
        System.out.println(function.call());
        System.out.println(function.call());
        System.out.println(function.call());
    }


    public String getMessage() {
        return String.format("invocation count: %d", ++invocationCount);
    }

    public static void main(String[] args) {
        final Example example = new Example();
        example.byValue(example.getMessage());
        example.byName(new IFunction< String >() {
            @Override
            public String call() {
                return example.getMessage();
            };
        });
    }
}
It look not so pretty as in Scala or Groovy. It remains to wait for Java 8 with Lambda Expressions...