Guava Strings utilities

31 10 2015

Almost every day you work with Strings. Guava has few convenient methods to make every day operations easier.

Strings class

Few static methods to notice:

  • Strings.padEnd(“foo”, 6, ‘xxx’) will pad provided string up to 6 chars with ‘x’ char. The result of this call will be “fooxxx”
  • Strings.padStart works analogously – it pads string from start. Strings.padStart(“foo”, 6, ‘xxx’) result will be “xxxfoo”
  • Strings.nullToEmpty(String) will turn null param to empty String of 0 length. If param was not null it will remain unchanged. It is advised to use to check method input params to avoid NPEs
  • Strings.emptyToNull(String) turns 0 length String to null object. If param war not an empty String, it will remain unchanged
  • Strings.isNullOrEmpty(String) replaces well known if(string != null && string.length() > 0) { … }. What a relief!

Take a look at a simple demo source code at my GitHub: https://github.com/yacekmm/looksok/tree/StringsDemo/Guava/GettingStarted

Advertisements




Guava Splitter class demo

24 10 2015

Split String with a delimiter to obtain the array of parts – a common task in programming. Especially when you work on parsing files (like CSV), input streams, etc.

Let’s take the row of a sample csv file:

String csvRow = "desk,,chair,table,couch,";

Notice that it’s a bit tricky, since that particular row has second and the last column empty.

Source Code

if you want to run it on your own, get the source code from my github: https://github.com/yacekmm/looksok/tree/SplitterDemo/Guava/GettingStarted

Java String.split()
Java’s split() works not intuitive, since the result of splitting:

String[] result = stringToSplit.split(",");

is:

[desk, , chair, table, couch]

Notice that there is no last column. Java by default threw it out. I prefer such decisions to be left to the programmer. It is easier to filter out empty items than figure out if there were really just 5 columns or did Java cut out some of them…

Guava Splitter
Guava Splitter API is as simple as Java’s, but the implementation is different. To split String do:

List<String> result = Splitter.on(",").splitToList(stringToSplit);

As a result you get a List that is eagerly evaluated:

[desk, , chair, table, couch, ]

Notice that here you have the last empty string item present.

Guava Lazy Splitter
If you care about performance and lazy evaluation may be helpful in your case you can use the split() method instead of splitToList():

Iterable result = Splitter.on(",").split(stringToSplit);

The split() result of course contains exactly the same result as splitToList().

The result is a lazy evaluated Iterator instance. That means that at this point you actually don’t have your string splitted but just ready to be splitted. It will be splitted when you actually call anything on an iterator.

I don’t know the implementation details but I assume that the whole string will not be splitted at once, but it will be splitted step by step when you take the next() item from the iterator. So the real performance gain will be noticable when you do not iterate all items but break at some point.

Otherwise (if you iterate all items) the whole string will be splitted anyway (the difference is only ‘when‘ it will be evaluated).

MapSplitter

If you have key-value map as a plain String like that:

String mapString = "office=desk,kitchen=table,living room=couch";

you can use MapSplitter class to convert it directly to Java Map:

Splitter.MapSplitter mapSplitter = Splitter.on(",").withKeyValueSeparator("=");
Map<String, String> result = mapSplitter.split(mapString);

And as a result you get the map:

{office=desk, kitchen=table, living room=couch}




Guava Joiner: Join all strings in an array or map

17 10 2015

How often do you have an array of strings:

List<String> listOfStrings = Lists.newArrayList("egg", "apple", null, "pineapple", "orange");

and needed to join its items in one string separated with commas (avoiding nulls) like that:

egg, apple, pineapple, orange

Source Code for this Guide is on my github: https://github.com/yacekmm/looksok/tree/master/Guava/GettingStarted

Doing it Java way
And how often did you use foreach loop and StringBuilder for it? Oh… and don’t forget to remove the last separator when you’re finished :) We see the code like that quite often, right?

StringBuilder builder = new StringBuilder();
for (String item : listOfStrings){
    if(item != null) {
        builder.append(item).append(SEPARATOR);
    }
}
builder.setLength(builder.length() - SEPARATOR.length());     //remove last SEPARATOR

With Java 8 it can be a bit simplier:

String result = listOfStrings.stream()
        .filter( item -> item != null)
        .reduce((s, s2) -> s + SEPARATOR + s2)
        .get();

Joining with Guava in one line
With Guava this is even shorter:

String result = Joiner.on(SEPARATOR).skipNulls().join(listOfStrings);

All in one line. No trailing separator that needs to be removed. Perfect – from now on you should never do it again without Guava :)

Can only Strings be Joined?
No – the toString() method will be called on each item of provided array. This way any custom object can be Joined.

Replacing null items in array with custom value
In previous example the null was ignored. Here is how to replace null with default value:

String result = Joiner.on(SEPARATOR).useForNull("EMPTY VALUE").join(listOfStrings);

Now the result will be:

egg, apple, EMPTY VALUE, pineapple, orange

Enhancing the Appendable object with more items
Joiner can be used with classes that implement Appendable interface (e.g. StringBuilder, FilewWriter) and append more items to it:

String result = Joiner.on(SEPARATOR).skipNulls().join(listOfStrings);

StringBuilder builder = new StringBuilder(result);
String extendedResult = Joiner.on(SEPARATOR).skipNulls().join(builder, "Strawberry");

The result is:

egg, apple, pineapple, orange, Strawberry

Joining the maps with custom key-value separator
I have a map:

Map<String, Integer> map

That holds a String as a key, and its length as a value. I can join items in this map easily with Joiner class, providing the key-value separator:

Joiner.on(SEPARATOR + "\n\t").withKeyValueSeparator(" has length of: ").join(map);

The result string is:

 orange has length of: 6,
apple has length of: 5,
egg has length of: 3,
pineapple has length of: 9

Source Code for this Guide is on my github: https://github.com/yacekmm/looksok/tree/master/Guava/GettingStarted





Guava ListenableFuture intro

13 09 2015

ListenableFuture is an abstraction to run asynchronous tasks in highly concurrent apps. It allows you to start a task, register callbacks and leave it to run and complete in separate thread. To fully explain it, let’s start with standard JDK Future.

JDK Fututre

JDK Future is dedicated to use with long running tasks. It returns you a Promise that may or may not yet have completed getting the result. The idea is to:

  1. execute the long running task
  2. assign the result to the Promise immediately (although the promise is not yet completed)
  3. perform any other operations you need (if any)
  4. few lines of code later you get the result of the Promise. If it already completed – you get the result immediately, else you wait until it completes.
  5. The effect is you could execute operations (from point 3.) while the Future was still evaluating, not blocking your thread. The thread is blocked already in point 4 where you potentially wait for the result blocking the main thread.

ListenableFuture

Guava’s ListenableFuture adds one more method to the Future interface:

addListener(Runnable, Executor)

Thanks to it you omit the point 5: waiting for Promise to fulfil. You just:

  1. Start the long running task and provide it with a success and failure callback
  2. evaluate the result in a callback, put the whole logic in there. It gets executed when task completes.

It is valuable in highly concurrent apps since its fully event driven notion.

The demo

My demo will show two ways of handling long running tasks.

The long runnning task emulation

Assume that I have long running method I need to execute in separate thread pool. To make it simple my task is blocking thread for five seconds by sleep():

public String executeLongRunningTask() throws InterruptedException {
    System.out.println(LocalTime.now() + " Starting evaluating long running tasks...");
    Thread.sleep(5000);
    return "Evaluation finished at " + LocalTime.now();
}

Main thread blocking execution

This is the simplest way to execute such a task:

private static void runBlockingOperationDemo() throws InterruptedException {
    System.out.println(LocalTime.now() + " Hello future!");
    
    final ListenableFutureDemo demo = new ListenableFutureDemo();
    String result = demo.executeLongRunningTask();
    
    System.out.println(LocalTime.now() + " Main method completed with result: " + result);
}

This way causes the main thread to wait until long running task execution completes (watch the timestamps):

21:19:37.305 Hello future!
21:19:37.318 Starting evaluating long running tasks...
21:19:42.319 Main method completed with result: Evaluation finished at 21:19:42.319

Note that between task execution start and main method execution completion there is a span of 5 seconds long.

ListenableFuture with callbacks

Let’s see how the app behaves when ListenableFuture is in action. The steps are:

  1. create executor service to submit future tasks
  2. execute non-blocking task in executor’s thread pool
  3. add success and failure handler that will be fired on task completion
private static void runListenableFutureDemo() {
    System.out.println(LocalTime.now() + " Hello future!");

    final ListenableFutureDemo demo = new ListenableFutureDemo();

    //create executor service to submit all future tasks
    ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

    //execute non-blocking task
    ListenableFuture<String> listenableFuture = service.submit(new Callable<String>() {
        @Override
        public String call() throws Exception {
            return demo.executeLongRunningTask();
        }
    });

    //add success and failure handler to listenableFuture object
    Futures.addCallback(listenableFuture, new FutureCallback<String>() {
        @Override
        public void onSuccess(String result) {
            System.out.println(LocalTime.now() + " Task completed successfuly with result: " + result);
        }

        @Override
        public void onFailure(Throwable t) {
            System.out.println(LocalTime.now() + " Task failed with result: " + t.getMessage());
        }
    });

    System.out.println(LocalTime.now() + " Main method completed but the result is still being calculated...");
}

The console output presents how it works (mind the timestamps and messages order):

21:23:09.623 Hello future!
21:23:09.663 Starting evaluating long running tasks...
21:23:09.685 Main method completed but the result is still being calculated...
21:23:14.668 Task completed successfuly with result: Evaluation finished at 21:23:14.667

Note that the main method has completed before the long running task is complete. The task execution completed 5 seconds later. Main thread did not have the task result. The result is known in success handler in callback. Pure asynchronous programming.

The demo source code

Get the code from my GitHub: https://github.com/yacekmm/looksok/tree/ListenableFutureDemo/Guava/Future





Guava RateLimiter to control the frequency of events

5 09 2015

Having a long running process, consisting of many small, fast steps, updating its listeners after processing each step?

Assume that you process the list of thousands items in a thread and want to show each processed item to the user. Processing each item is very fast, so the updates will be send to the GUI very frequently. You do not want to notify the GUI listener so often. But you want to refresh the gui twice per second, not more.

This is what RateLimiter can do: limit the access to the resources to prevent too frequent calls.

GuiUpdater

For sake of simplicity my GuiUpdater just prints message with a timestamp on System.out:

public class ProgressGuiUpdater implements GuiUpdater{
    @Override
    public void updateGui(String message) {
        System.out.println(LocalDateTime.now().toLocalTime() + ": " + message);
    }
}

The LongRunningProcess

My process consists of many small steps. In each step I update the GUI via the injected updater. Calling this loop with 15000 iterations lasts around 3 seconds.

@Override
public void run() {
    for (int i = 0; i < stepsCount; i++) {
        guiUpdater.updateGui("This is the item number" + i);
    }
}

GUI gets updated around 5000 times per second. For average app it is way too often. This is the fragment of console output (mind the timestamps):

16:53:10.025: This is item number 1
16:53:10.026: This is item number 2
16:53:10.026: This is item number 3
16:53:10.027: This is item number 4
16:53:10.027: This is item number 5
16:53:10.028: This is item number 6
16:53:10.029: This is item number 7

Limit the updates frequency

RateLimiter will limit the access to the updater. It will stop the thread execution until the specified time will pass (remember the semaphores in Java?). After it will acquire the access, the thread will be unblocked and updater method will be called. Before calling the updater method I need to acquire the RateLimiter:

@Override
public void run() {
    for (int i = 0; i < stepsCount; i++) {
        double waitTime = rateLimiter.acquire();
        guiUpdater.updateGui("This is the item number " + i + " (I've waited for acquire for " + waitTime + " seconds)");
    }
}

The creation of rateLimiter is:

RateLimiter.create(2.0)

As a parameter I pass the number of times per second the rate limiter can acquire the lock.

The result of that configuration is (mind the timestamps and waiting times):

18:09:15.364: This is the item number 0 (I've waited for acquire for 0.0 seconds)
18:09:15.539: This is the item number 1 (I've waited for acquire for 0.113705 seconds)
18:09:16.028: This is the item number 2 (I've waited for acquire for 0.486599 seconds)
18:09:16.527: This is the item number 3 (I've waited for acquire for 0.498785 seconds)
18:09:17.027: This is the item number 4 (I've waited for acquire for 0.498922 seconds)
18:09:17.527: This is the item number 5 (I've waited for acquire for 0.49909 seconds)
18:09:18.027: This is the item number 6 (I've waited for acquire for 0.499802 seconds)
18:09:18.529: This is the item number 7 (I've waited for acquire for 0.499185 seconds)
18:09:19.034: This is the item number 8 (I've waited for acquire for 0.496844 seconds)
18:09:19.527: This is the item number 9 (I've waited for acquire for 0.492872 seconds)

That’s it! Get the source code
Source code for this demo is on my github: https://github.com/yacekmm/looksok/tree/RateLimiterDemo/Guava/RateLimiter





Guava null checkers

30 08 2015

A short demo introducing methods of handling null objects, null checks and null comparisons in guava. These guava methods will reduce the amount of ifs, NPEs and try-catch blocks.

Here is what you can do:

Null safe equality check

// --------- null-safe equality check ---------
String nullString = null;
String nameString = "Jack";

Objects.equal(nullString, nameString);  //returns false
nullString.equals(nameString);          //throws NPE
// ---------

Get default value if the first value was null

// --------- use the default value if previous arguments were null ---------
String login = "userLogin";
String name = MoreObjects.firstNonNull(methodThatMayReturnNull(), login);

//is the same as Java's:
name = methodThatMayReturnNull();
if(name == null)
    name = login;
// ---------

Check if argument is null

// --------- Argument check against null ---------
String nullArgument = null;
Preconditions.checkNotNull(nullArgument, "Argument was null!");   //throws NPE if argument is null
// ---------

Demo source Code

Download source code with these examples from my github: https://github.com/yacekmm/looksok/tree/NullCheck/Guava/NullCheck





Guava collection initializers

22 08 2015

Java requires quite verbose collection initialization (due to generics) like this:

Map<String, Map<String, Integer>> lookupTraditional = new HashMap<String, Map<String, Integer>>();

It barely fits one line… It’s long and readability is reduced.

Java 7 introduced the Diamond Operator, so the developer does not have to repeat all the types declaration after the new operator:

Map<String, Map<String, Integer>> lookupJava7 = new HashMap<>();

Guava creators’ idea is to use static factory method pattern to shorten the collection initialization:

Map<String, Map<String, Integer>> lookup = Maps.newHashMap();

Factory methods are overloaded to accept params thet fill the collection with items. To create List of names use:

List<String> names = Lists.newArrayList("Bob", "Gwen", "Justin");

Get the code to experiment

If you are willing to experiment with Guava feel free to use my project skeleton with initializers demo: https://github.com/yacekmm/looksok/tree/InitializersDemo/Guava/Initializers








%d bloggers like this: