Oct 3, 2018 - Neat Java 8 features - Stream API

Comments

Neat Java 8 features - Stream API

This is the second of three posts and is about the Stream API.

Previous post: Neat Java 8 features - Lambda expressions Next post: Neat Java 8 features - Concurrency API

Stream API

These methods make it easier to work with Collections. What are you typically doing with a collection? You’re iterating over it, in order modify certain/all objects, find specific objects, filter the collection, sort the collection, again and again… And you always start with for(...) {...} or while(...) {...}.

For example if you have a Collection of Items

    List<Item> collection = new ArrayList<Item>();
    for (int i=0; i < 1000; i++)
        collection.add(Item.randomInstance());

    static class Item {
        private static Random rand = new Random();
        
        String name;
        double price;

        Item(String name, double price) {
            this.name = name;
            this.price = price;
        }
        
        static Item randomInstance() {
            String name = UUID.randomUUID().toString().substring(0, 5);
            double amount = rand.nextDouble()*10;
            return new Item(name, amount);
         }
    }

A common task is to filter this collection:

    List<Item> filtered = new ArrayList<Item>();
    for(Item i : collection) {
        if (i.price > 5)
            filtered.add(i);
    }
    System.out.println(filtered.size()+" items are more expensive than 5.00 whatever." );

With the stream methods you can do this as a one liner:

    filtered = collection.stream().filter(i -> i.price > 5).collect(Collectors.toList());
    System.out.println(filtered.size()+" items are more expensive than 5.00 whatever." );

You can also do some more fancy things without all the usual for/while loop bloat:

    // Get the names of all items with a price > 9.5
    // as alphabetically sorted list
    List<String> names = collection.stream()
                         .filter(i -> i.price > 9.5)
                         .map(i -> i.name)
                         .sorted(String::compareTo)
                         .collect(Collectors.toList());
    // print the list
    names.stream().forEach(System.out::println);

Apart from the simplification of the code a big advantage of the stream API is, that it is very easy to parallelize tasks. If you have for example a fairly expensive operation which does something with your Item:

    Function<Item, Item> expensiveOperation = i -> {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
        }
        i.name = i.name.toUpperCase();
        return i;
    };

…and you want to run that over the whole collection, you could use the for loop:

    long t = System.currentTimeMillis();
    for(Item i : collection) {
        expensiveOperation.apply(i);
    }
    t = System.currentTimeMillis() - t;
    System.out.println("for loop took "+t+" ms.");
    
    // output: for loop took 11793 ms.

Or you could very easily parallelize it and make use of all your CPU cores:

    long t = System.currentTimeMillis();
    collection.parallelStream().map(expensiveOperation).collect(Collectors.toList());
    t = System.currentTimeMillis() - t;
    System.out.println("parallelStream() took "+t+" ms.");
    
    // output: parallelStream took 1498 ms.

But there is a caveat, that’s why I said use parallelStream() only for ‘fairly expensive’ operations:

  • Parallelization comes with an overhead. If the operation is very simple and quick, the sequential for loop is probably faster than Java having to deal with the parallelization.
  • The stream API uses a common thread pool. If it’s possible that the operation could take a long time to finish, you easily could use up all the available threads of the pool and block other faster / more important parallel tasks.

Sep 26, 2018 - Neat Java 8 features - Lambda expressions

Comments

Neat Java 8 features - Lambda expressions

At work I’m still bound to Java 7, which is a bit a pity because since Java 8 there are some pretty neat features available.

This first of three posts is about Lambda expressions.

Next posts:

Lambda expressions

Lambda expressions allow you to pass functions on to methods, objects, etc.

E.g. you can create a function with the -> operator:

// A function which takes an Integer and returns a String:
Function<Integer, String> func = i -> {
    return  "This is '"+i+"'' as String";
};

You can then pass it on to another object, e. g.

someObject.setSomeFunction(func);

In the object you can make use of this function by calling its apply method

func.apply(100);

Here’s a complete example:

import java.util.function.Function;

public class Test {

    private Function<Integer, String> func;
    
    public void setFunction(Function<Integer, String> func) {
        this.func = func;
    }

    public String doSomething(int i) {
        return func.apply(i);
    }
    
    public static void main(String[] args) {
        Test test = new Test();
        
        Function<Integer, String> func = i -> {
            return "This is '"+i+"' as String";
        };
        
        test.setFunction(func);
        
        String result = test.doSomething(100);
        
        System.out.println(result);
    }
}

Instead of defining the function and then passing it on you more commonly see something like this, which is equivalent but shorter:

test.setFunction(i -> "This is '"+i+"' as String");

Function is a Functional interface, which means an interface which only has one abstract method. With the -> operator you effectively provide the implementation for this abstract method.

You can define your own Functional interfaces. Let’s say you have a Handler interface which provides a method to process a certain request, in this example case consisting of a String and an integer, but that could as well be an HTTP request, UI event, etc.

@FunctionalInterface
public interface Handler {
    public String handle(String item, int amount);
}

Annotate it with the FunctionalInterface annotation. It’s not necessary but helps spotting issues early!

You can use the Handler interface in other classes for example like this (directly providing an implementation via the -> operator):

public class Test {

    private Handler handler;
    
    public void setHandler(Handler handler) {
        this.handler = handler;
    }
    
    public String doSomething(String arg1, int arg2) {
        return handler.handle(arg1, arg2);
    }
    
    public static void main(String[] args) {
        Test test = new Test();

        test.setHandler((x, y) -> {
            return "Successfully handled " + x + " and " + y;
        });

        String result = test.doSomething("Test", 1);
        System.out.println(result);
    }
}

Where possible many core Java interfaces have been annotated with the FunctionalInterface Annotation, for example the Actionlistener, so that you can easily provide an implementation:

JButton button = new JButton("Click me");
button.setActionCommand("doSomething");
button.addActionListener(e -> {
    System.out.println("Handling event "+e.getActionCommand());
});

Coming back the Handler example: Instead of the ‘inline’ implementation …

test.setHandler((x, y) -> {
    return "Successfully handled " + x + " and " + y;
});

… you can of course use already implemented methods:

HandlerImpl h = new HandlerImpl();
test.setHandler(h::handle);

This :: syntax is a method reference (also a new feature of Java 8)

If this method is a static method, this could be even shorter as you don’t need an instance:

test.setHandler(StaticHandlerImpl::handle);

Next post: Neat Java 8 features - Stream API

Sep 5, 2018 - Python decorators

Comments

Python decorators

I’m not a big fan of Python (yet), but it certainly has some nice features, like ‘decorators’.

A decorator wraps a method and lets you do specific things before and after the method is called. This can be very useful, to check the state of the application before the method is called (for example if the user is logged in, has the permission to execute the method, etc.).

I recently had a class with various methods which had to connect to a remote service, do some stuff with the service, and then disconnect again to clear up the resources. I could have added the same connect and disconnect code to each of the methods, but using a decorator is of course much easier and maintainable. Here’s how it looked like:

I created a decorator ‘service_required’ which connects to the service and makes the service accessible to the class in which it is needed (see the ‘service’ variable). It is little bit like ‘dependency injection’ which Python doesn’t offer per se. Then it calls the decorated function. Thereafter it disconnects from the service again.

Note 1: The wrapper function takes the arguments ‘self’, ‘*args’, and ‘**kwargs’, that is ‘self’ a reference to the ‘calling’ class (that’s needed to set the ‘service’ variable of the ‘calling’ class), ‘*args’ and ‘**kwargs’ which are the arguments passed to the decorated methods.

Note 2: The decorator calls the decorated function, stores the returned value, does its cleanup tasks (disconnecting from the server) and then returns this value. This is important, otherwise the return value of the decorarated method is simply lost.

from functools import wraps


class Service():
    """
    This is an example service, which could be some remote
    service endpoint, a database, etc. In order to be used
    we must first connect to it and then after our request
    is finished we have to disconnect again, so that any
    resources are released again.
    """

    connected = False

    def connect(self):
        self.connected = True
        print "Connection established."

    def add_one(self, value):
        if not self.connected:
            raise Exception("This service is not online")
        return value + 1

    def disconnect(self):
        self.connected = False
        print "Connection closed."


def service_required(func):
    """
    Decorator which makes sure that the service is
    connected and gets properly disconnected again
    after a method call.
    """

    @wraps(func)
    def _wrapper(self, *args, **kwargs):
        self.service = Service()
        self.service.connect()

        value = func(self, *args, **kwargs)

        self.service.disconnect()
        self.service = None
        return value

    return _wrapper


class Example():
    """
    An example class which uses the service
    to do something.
    """

    service = None

    @service_required
    def do_something(self):
        value = self.service.add_one(1)
        print value

    @service_required
    def and_again(self):
        value = self.service.add_one(2)
        print value


example = Example()
example.do_something()
example.and_again()

Edit (2018/09/06)

I just noticed, an even better implementation is to wrap the function call in a try finally statement, this way you can be really sure that the close methods are called, even if the function call throws an exception. The only way the close method could be missed is if the function call terminates the application (either deliberatly or due to an error).

The decorator would then look like this:

def service_required(func):
    """
    Decorator which makes sure that the service is
    connected and gets properly disconnected again
    after a method call.
    """

    @wraps(func)
    def _wrapper(self, *args, **kwargs):
        self.service = Service()
        self.service.connect()

        try:
            return func(self, *args, **kwargs)
        finally:
            self.service.disconnect()
            self.service = None

    return _wrapper