VOOZH about

URL: http://kingsfleet.blogspot.com/search/label/lambda

⇱ G's Blog: lambda


skip to main | skip to sidebar
Showing posts with label lambda. Show all posts
Showing posts with label lambda. Show all posts

Monday, August 15, 2016

What is bound to generic types for method references in java 8, types and exceptions

So most of the time you are probably aware of method references that either reference instance of static methods directly, and they are useful but not necessarily that interesting.

Integer example = 1;

// We can bind the instance variables, in this case just the return type is bound but there couple be method parameters also
Supplier<String> s = example::toString;

// We can bind to static method, here the generic parameter are the method parameter and return type
Supplier<Long> f = System::currentTimeMillis;
Function<Integer,Integer> f = example::compareTo;


A less common formulation is to pass in instance methods and find the first generic parameter of of the function to be the type, this allows you to easily pass in a range of actions to operate on a common type:

Function<Integer,String> f = Integer::toString

For example you can create an equals method that works on a subset of properties using functions mapped to instance methods as in the above example:

public static <T> boolean equals(T one, T two, Function<? super T, ?>... accessors) {

 if (one == two) {
 return true;
 } else if (one==null || two==null) {
 return false;
 }

 return Stream.of(accessors).allMatch(accessor ->
 Objects.equals(accessor.apply(one),accessor.apply(two)));
}

if (equals(one, two, Thing::getName, Thing:getOtherProperty)) ...;



Finally you can also bind the exception thrown from the method to one of the generic parameters. (Here I am using ThrowingException and ThrowingSupplier my home brew interfaces that are like there namesakes but have a generic parameter E for the exception thrown) This allows you to make you "closure" transparent to exceptions. This is more useful in a lot of cases when compared to the Stream throw nothing and "throws Exception" extremes.

ThrowingException<String,Integer,NumberFormatException> te = Integer::parseInt;


You can write funky closure methods that will throw different exceptions based on the passed in method reference does, no more catch (Exception).

public static <T, E extends Exception> T withCC(Class<?> contextClass, 
 ThrowingSupplier<T,E> action) throws E {

 Thread t = Thread.current();
 ClassLoader cl = t.getContextClassLoader();
 try {
 t.setContextClassLoader(contextClass.getClassLoader());
 return action.get();
 } finally {
 s.setContextClassLoader(cl);
 }
}
 

// Throws IOException, complier knows that this method call throws IOException

String value = withCC(Example.class, () -> {
 ...
 ... new FileOutpuStream(file); ...
 ...
});

// Throws another exception, complier knows that this method call throws RMIExeption

String value = withCC(Example.class, () -> {
 ...
 throw new RMIException();
 });


Once you understand the last two, method reference start to become far more interesting.
Posted by Gerard Davison at 3:52 PM 0 comments 👁 Image
Labels: jdk8, lambda

Thursday, March 10, 2016

Lambda of Lambda, if/else from an Optional

So I got frustrated with two limitations of the Optional interface in JDK 8. The first problem is that there is no obvious way to perform an else operation in a block as there is only a isPresent method unless you are using an old school if statement. The second problem is of course the old chestnut that even if you could do that the methods would not be able to throw a checked exception. (Yes you can wrap with a RuntimeException but it is not the prettiest.)

The workaround I found was to use the map function as the success case and the orElseGet to return the failure case. In both branches the code returns an instance of ThrowingRunnable by having a lambda return a lambda. The run() is then called at the end and it can throw any exception it wants to.

@FunctionalInterface
public interface ThrowingRunnable<E extends Throwable> {
 
 public void run() throws E;
}



Optional<Credential> credential = ....

credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
 PasswordWrapper pw = auth.getToken();
 ... // something that might throw an IOException
 }).orElseGet(() -> () -> {
 response.setStatus(401);
 LOGGER.log(Level.INFO, "credential is not found");
 }
 ).run();


This is possibly excessive for this particular use case; but I can see this technique being useful elsewhere and it is worth knowing what it looks like so it is not a surprise in others code.

Update 14th March 2016: Thanks to Michael Rasmussen on the DZone version of this article he noted I could use orElse rather than orElseGet to remove the second double lambda.

credential.<ThrowingRunnable<IOException>>map(auth -> () -> {
 PasswordWrapper pw = auth.getToken();
 ... // something that might throw an IOException
 }).orElse(() -> {
 response.setStatus(401);
 LOGGER.log(Level.INFO, "credential is not found");
 }
 ).run();



Posted by Gerard Davison at 10:20 AM 0 comments 👁 Image
Labels: java, jdk8, lambda

Tuesday, January 7, 2014

Post-hoc tracing using a debugger

Once nice little features of most debuggers that I have been exercising recently is the ability to log information on a breakpoint. This can be a really useful was to understand code without having to modify it is involve byte code modification.


Let's consider this very trivial and inefficient implementation of a function to return the n'th number in the Fibonacci sequence.


public class Fib {



 public long fib(long number) {
 return number < 1 ? 0 : // Breakpoint here
 number < 2 ? 1 : fib(number - 2) + fib(number - 1);
 }




 public static void main(String[] args) {

 Fib fib = new Fib();
 System.out.println(fib.fib(10L));

 }

}

Now we add a simple breakpoint, I am going to modify it slightly so that it doesn't halt; but it will log a simple expression which gives us the current value of number

This gives you the following output for our rather inefficient code:

ebugger connected to local process.
Source breakpoint: Fib.java:11, evaluate(number)=10 (long)
Source breakpoint: Fib.java:11, evaluate(number)=8 (long)
Source breakpoint: Fib.java:11, evaluate(number)=6 (long)
Source breakpoint: Fib.java:11, evaluate(number)=4 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
Source breakpoint: Fib.java:11, evaluate(number)=0 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=3 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
... sometime later
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
Source breakpoint: Fib.java:11, evaluate(number)=2 (long)
Source breakpoint: Fib.java:11, evaluate(number)=0 (long)
Source breakpoint: Fib.java:11, evaluate(number)=1 (long)
55

So what we have done here is to add trace post-hoc, you might not even have access to the source and still be able to get useful information out of what the code is doing.

Now the obvious take away from the above example is that we are computing the same value over and over again. So here is another version of the code which instead uses a Map to store previously computed values in the sequence. Note also it is more of a pain to add trace to this code than in the previous case without making the Lambda less pretty.

import java.util.HashMap;
import java.util.Map;

public class Fib {


 Map<Long, Long> data = new HashMap<>();
 {
 data.put(1L, 1L);
 }


 public long fib(long number) {
 return data.computeIfAbsent(number,
 n -> n < 1 ? 0 : fib(n - 2) + fib(n - 1)); // Breakpoint here
 }




 public static void main(String[] args) {

 Fib fib = new Fib();
 System.out.println(fib.fib(10L));

 }

}

It is worth noting two things here, first of all your breakpoint log expression should be evaluating the value of the Lambda parameter n and that the second is that you should always put your expression on a new line so that future developer can easily breakpoint it. (Not matter now much smaller/ prettier/ clever it would look if you put the code on one).

So the trace output is now as follows, much better as each value is only computed the once.

Debugger connected to local process.
Source breakpoint: Fib.java:17, evaluate(n)=10
Source breakpoint: Fib.java:17, evaluate(n)=8
Source breakpoint: Fib.java:17, evaluate(n)=6
Source breakpoint: Fib.java:17, evaluate(n)=4
Source breakpoint: Fib.java:17, evaluate(n)=2
Source breakpoint: Fib.java:17, evaluate(n)=0
Source breakpoint: Fib.java:17, evaluate(n)=3
Source breakpoint: Fib.java:17, evaluate(n)=5
Source breakpoint: Fib.java:17, evaluate(n)=7
Source breakpoint: Fib.java:17, evaluate(n)=9
55

The screen grabs in this blog are from Jdeveloper; but similar features are available in Intelij, Netbeans and if you are a bit crafty you can get something similar in Eclipse.

Posted by Gerard Davison at 4:10 PM 0 comments 👁 Image
Labels: debugging, java, lambda

Thursday, December 19, 2013

Lambda'ery WebSocket code (from UKTECH13 presentation)

At UKTECH13 I was asked to post the source code to the WebSocket used in my presentation, primarily because it was using JDK 8 constructs that were unfamiliar to many. One of the very nice things about the changes to the languages and the supporting library changes is the lack of if statements in the code.

I would note that in a real world chat application that it unlikely different rooms would have different resource URIs but for the purposes of the presentation this made sense.

package websocket;

import static java.util.Collections.emptySet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/chat/{room}")
public class ChatService {

 private static final Set<Session> EMPTY_ROOM = emptySet();

 static final ConcurrentMap<String, Set<Session>> rooms =
 new ConcurrentHashMap<>(); 


 @OnOpen
 public void onOpen(Session peer, @PathParam("room") String room) {
 rooms.computeIfAbsent(room,
 s -> new CopyOnWriteArraySet<Session>()).add(peer);
 }

 @OnClose
 public void onClose(Session peer, @PathParam("room") String room) {

 rooms.getOrDefault(room, EMPTY_ROOM).remove(peer);
 
 }

 @OnError
 public void onError(Session peer, Throwable th,
 @PathParam("room") String room) {
 System.out.println("Peer error " + room + " " + th);
 }


 @OnMessage
 public void message(String message, Session peer,
 @PathParam("room") String room) {

 // Send a message to all peers in a room who are not the current
 // peer and are still open. Send the message asynchronously to ensure
 // that the first client is not hung up. 

 rooms.getOrDefault(room, EMPTY_ROOM).parallelStream()
 .filter(s -> s != peer && s.isOpen())
 .forEach(s -> s.getAsyncRemote().sendObject(message));
 };

}

One of the problem with the above design is that there is no error logging when an invalid room is used. This could be useful to diagnose errors. Not wanting to use any conditional statements you could use an Optional object:

import java.util.Optional;


 @OnClose
 public void onClose(Session peer, @PathParam("room") String room) {

 Optional.ofNullable(rooms.get(room))
 .orElseThrow(() -> new IllegalStateException("Cannot find room " + room))
 .remove(peer);
 
 }


Of course you might want this on your method objects, so you can use default methods to create a mixin for this on all your Map objects with a trivial subclass.

import java.util.Optional;


 public interface OptionalMap<K,V> extends ConcurrentMap<K,V> {
 public default Optional<V> find(K key) {
 return Optional.ofNullable(get(key));
 }
 }

 public static class OptionalHashMap<K,V> extends ConcurrentHashMap<K,V>
 implements OptionalMap<K,V> {
 
 }
 

 static final OptionalMap<String, Set<Session>> rooms =
 new OptionalHashMap<>(); 


 @OnClose
 public void onClose(Session peer, @PathParam("room") String room) {

 rooms.find(room)
 .orElseThrow(() -> new IllegalStateException("Cannot find room " + room))
 .remove(peer);
 
 }





Whilst working on my presentation it became apparent that it was also possible to use the "openSessions" and "getUserProperties" method to store discrimination data against the Session. I don't have enough experience yet to say which is the better design for a particular case.

package websocket;


import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/chat/{room}")
public class ChatService {

 private static final String ROOM_PROPERTY = "ROOM";


 @OnOpen
 public void onOpen(Session peer, @PathParam("room") String room) {
 peer.getUserProperties().put(ROOM_PROPERTY, room);
 }

 @OnClose
 public void onClose(Session peer, @PathParam("room") String room) {
 
 // No need to tidy up and data is store against peer
 }

 @OnError
 public void onError(Session peer, Throwable th,
 @PathParam("room") String room) {
 System.out.println("Peer error " + room + " " + th);
 }


 @OnMessage
 public void message(String message, Session peer,
 @PathParam("room") String room) {

 peer.getOpenSessions().parallelStream()
 .filter(s -> room.equals(s.getUserProperties().get(ROOM_PROPERTY)))
 .filter(s -> s != peer && s.isOpen())
 .forEach(s -> s.getAsyncRemote().sendObject(message));
 };

}
Posted by Gerard Davison at 4:26 PM 0 comments 👁 Image
Labels: java, jdk8, lambda, web socket

Wednesday, December 4, 2013

Lambda, will it serialize?

So I have been ponder an enhancement required on the Tyrus project that would allow a user to broadcast to a subset of client connected to a URL across a cluster of machines. There are various way of doing this; but since I was playing with JDK 8 this problem definitely looked like a nail.

To this end I created a simple unit test class that would take my filter, serialise it to disk, read it back and in then execute it. It had a instance field "VALUE" that we could use to reference directly or indirectly to find out what would cause the serialisation to fail.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.util.function.Predicate;

import org.junit.Test;

public class SerializablePredicateFilterTest {

 public String VALUE = "Bob";

 public interface SerializablePredicate<T> extends Predicate<T>, Serializable {

 }


 public <T> void filter(SerializablePredicate<T> sp, T value) throws IOException, ClassNotFoundException {


 sp.getClass().isLocalClass();

 File tempFile = File.createTempFile("labmda", "set");


 try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(tempFile))) {
 oo.writeObject(sp);
 }


 try (ObjectInput oi = new ObjectInputStream(new FileInputStream(tempFile))) {
 SerializablePredicate<T> p = (SerializablePredicate<T>) oi.readObject();

 System.out.println(p.test(value));
 }


 }

}


So just to calibrate lets make sure that an anonymous inner class will fail, because it will always contain a reference to enclosing object....

 @Test(expected = NotSerializableException.class)
 public void testAnonymousDirect() throws IOException, ClassNotFoundException {

 String value = VALUE;


 filter(new SerializablePredicate<String>() {

 @Override
 public boolean test(String t) {
 return value.length() > t.length();
 }
 }, "Bob");

 }


The same is true for local classes, what you don't use local classes?

 @Test(expected = NotSerializableException.class)
 public void testLocalClass() throws IOException, ClassNotFoundException {

 class LocalPredicate implements SerializablePredicate<String> {
 @Override
 public boolean test(String t) {
 // TODO Implement this method
 return false;
 }
 }

 filter(new LocalPredicate(), "Bobby");

 }


So a standalone class will of course work, in this case a nested class for convenience.

 public static class LengthPredicate implements SerializablePredicate<String> {

 private String value;


 public LengthPredicate(String value) {
 super();
 this.value = value;
 }

 public void setValue(String value) {
 this.value = value;
 }

 public String getValue() {
 return value;
 }

 @Override
 public boolean test(String t) {
 // TODO Implement this method
 return false;
 }
 }


 @Test
 public void testStaticInnerClass() throws IOException, ClassNotFoundException {

 filter(new LengthPredicate(VALUE), "Bobby");

 }


So lets get down with JDK 8, it turns out that my first try also fails but it does confirm that the serialisation is quite happy to take a Lambda in general.

 @Test(expected = NotSerializableException.class)
 public void testLambdaDirect() throws IOException, ClassNotFoundException {


 filter((String s) -> VALUE.length() > s.length(), "Bobby");

 }


A slight modification to copy the value into a effectively final attributes, and voila the lambda is now serialised and retrieved properly.

 @Test
 public void testLambdaInDirect() throws IOException, ClassNotFoundException {

 String value = VALUE;

 filter((String s) -> value.length() > s.length(), "Bobby");

 }


And of course if the value is a simple method parameter it also works fine.

 @Test
 public void testLambdaParameter() throws IOException, ClassNotFoundException {

 invokeWithParameter(VALUE);

 }

 private void invokeWithParameter(String value) throws java.lang.ClassNotFoundException, java.io.IOException {
 filter((String s) -> value.length() > s.length(), "Bobby");
 }


So the answer is yes, you can get it to serialise if you are a bit careful.

Posted by Gerard Davison at 3:04 PM 1 comments 👁 Image
Labels: jdk8, lambda
Subscribe to: Posts (Atom)