Monthly Archives: March 2017

Converter

public static void converterTest() {
    BiMap<Integer, String> biMap = HashBiMap.create();
    biMap.put(1, "a");
    biMap.put(2, "b");
    biMap.put(3, "c");
    Converter<Integer, String> converter = Maps.asConverter(biMap);
    System.out.println(converter.convert(1));
    System.out.println(converter.reverse().convert("b"));
}

Optional

Optional can avoid null of an Object.

public static void nullable() {
    Optional<Integer> i =  Optional.fromNullable(null);
    System.out.println(i.or(2));    // output 2, because is null
    System.out.println(i.get());    // IllegalStateException
}

public static void absent() {
    Optional<Integer> i =  Optional.absent();
    System.out.println(i.or(2));    // output 2, because value is absent
    System.out.println(i.get());    // IllegalStateException
}

public static void of() {
    Optional<Integer> i =  Optional.of(1);
    System.out.println(i.get());    // output 1
    System.out.println(i.or(2));    // return 1, because it has value
}

Best use case is that when we initialize the value, we use Optional.fromNullable(). When we get the value, we use Optional.or(), Optional.orNull().

Reference: https://www.tutorialspoint.com/guava/guava_optional_class.htm

CacheBuilder

Below one is the nice cache scheme. Just to remind that LoadingCache is an abstract class, not a interface. So it can’t be wrote in lambda expression.

public static void cacheBuilderCase() throws Exception {
    LoadingCache<Integer, String> memo = CacheBuilder.newBuilder().build(
            new CacheLoader<Integer, String>() {
                public String load(Integer key) throws Exception {
                    return String.valueOf(key);
                }
            });

    System.out.println(memo.get(1));
    System.out.println(memo.get(2));
    System.out.println(memo.get(1)); // will get from cache
    System.out.println(memo.get(2)); // will get from cache
}

memo.getIfPresent() return the value. If the value doesn’t exist, it returns null, and it won’t store the value.

Supplier memoization

Below code is a simple way for memoization:

private String value;

public String getValue() {
    if (value == null) {
        value = "abcd";
    }
    return value;
}

This can be also wrote in Guava way:

Supplier<String> memo = Suppliers.memoize(() -> {
    return "abcd";  // inside function
});
System.out.println(memo.get());  // will call the function
System.out.println(memo.get());  // will not call the function, directly get from cache.

 

Create ExecutorService and ListeningExecutorService

Executor is a interface, there is no way to create it.

Normally, there are 2 ways to create ExecutorService:

ExecutorService service = Executors.newFixedThreadPool(10);
ExecutorService service = Executors.newSingleThreadExecutor();

Normally, use decorator to create ListeningExecutorService by ExecutorService:

ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

Compared to Executor, ExecutorService has shutdown function.

ExecutorService returns Future, ListeningExecutorService returns ListenableFuture.

Compared to Future, ListenableFuture can attach a callback, which will be called when result is available. The callback and submit doesn’t has an order sequence.

public static void callBack() throws Exception{
    ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
    Callable<String> c = () -> {
        return "abcd";
    };
    ListenableFuture<String> future = service.submit(c);
    Runnable callBack = () -> {
        System.out.println("in callback: " + java.lang.Thread.activeCount());
    };
    future.addListener(callBack, service);
    System.out.println(future.get());
}

Above code will generate 2 threads. service generates 2 threads. One is called by service.submit, another is called by future.addListener(callBack, service). These 2 threads doesn’t has sequence order.

 

submit, execute, callable, runnable

ExecutorService and ListeningExecutorService has submit() and execute() funciton:

Future<T> submit(Callable<T> task)
Future<?> submit(Runnable task)
void execute(Runnable command)

Both ExecutorService and ListeningExecutorService can submit a Runnable and Callable parameter.

Submit a Callable:

public static void submitCallable() throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Callable<String> r = () -> {
        return "abcd";
    };
    Future<String> future = executorService.submit(r);
    System.out.println(future.get());
    executorService.shutdown();
}

Submit a Runnable :

public static void submitRunnable() throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Runnable r = () -> {
        System.out.println(1);
    };
    Future future = executorService.submit(r);
    System.out.println(future.get());   // future of submitting a runnable is always null
    executorService.shutdown();
}

 

Execute a Runnable:

public static void executeCallable() throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Runnable r = () -> {
        System.out.println("abcd");
    };
    executorService.execute(r);
    executorService.shutdown();
}

Code on git

Stop ExecutorService

Look at this code, it won’t stop:

public static void main(String[] args) throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Runnable r = () -> {
        System.out.println(1);
    };
    executorService.submit(r);
}

Main reason is that it didn’t call executorService.shutdown();

Exector is a simple interface. It only has a execute() function. ExecutorService has shutdown() function, which can stop the thread.

So below is the complete one:

public static void main(String[] args) throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Runnable r = () -> {
        System.out.println(1);
    };
    executorService.submit(r);
    executorService.shutdown();
}