Java 8: Chain consumer <Y> for function <X, Y>

While exploring the new features of Java 8, I came across a desire to create a Consumer<X> by binding Consumer<Y> to Function<X,Y> .

It makes sense? And if so, what will a good (general) solution look like?

What I tried (rather, a special case with an example):

Considering

 @FunctionalInterface public interface PartialFunction<X, Y> { Y apply(X x) throws Exception; } 

and

 import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; public class PartialFunctions { public static <X, Y> Function<X, Optional<Y>> withOptionalResults(final PartialFunction<X, Y> funcThatThrows) { return z -> { try { return Optional.of(funcThatThrows.apply(z)); } catch (final Exception e) { return Optional.empty(); } }; } public static <X, Y> Consumer<X> acceptOnSuccess(final PartialFunction<X, Y> g, final Consumer<Y> c) { return x -> withOptionalResults(x).apply(t).ifPresent(c); } } 

I get a possible use, for example:

 files.forEach(PartialFunctions.<File, BufferedImage>acceptOnSuccess( ImageIO::read, images::add)); 

However, the need for an explicit general specification is not optimal. Hope something better?

+6
source share
4 answers
 interface IgnoreThrowing<F,V> extends Function<F,V> { public default V apply(F from) { try { return ignore(from); } catch(Exception e) { return null; } } public V ignore(F from) throws Exception; } class Throwables { public static <F,V> Function<F,V> ignore(IgnoreThrowing<F,V> f) { return f; } } static { files.map(Throwables.ignore(ImageIO::read)).collect(...) } 

This will be better if you add a Collector that ignores NULL values ​​as input.

edit: I wrote this without syntax checking or compilation, so I’m not completely sure about the default layout and whether the compiler can successfully determine the parameters of the function chain.

+8
source

You can extend the Function interface like this:

 public interface ComposableFunction<T, R> extends Function<T, R> { default Consumer<T> andThen(Consumer<R> after) { Objects.requireNonNull(after); return (T t) -> {after.accept(apply(t));}; } } 

And then use it like this:

 ComposableFunction<Throwable, String> getMessage = Throwable::getMessage; Consumer<String> log = System.out::println; Consumer<Throwable> logMessage = getMessage.andThen(log); 
+2
source

Can you try something like this?

 public void lambdaChaining() { System.out.println("\nlambda chaining:"); List<String> l = Arrays.asList("1", "22", "333", "4444", "55555", "666666", "7777777", "88888888", "999999999"); Function<String, ?> f = s -> s.length(); Consumer<String> c = s -> System.out.println(f.apply(s));; l.forEach(c); } 
+1
source

another option (and a more general case) is to use new Function<X,Y>(...).andThen(new Function<Y,Z>(...)) . I would not mix consumers and functions, but rather chains, and then eat consumers (who may also have been riveted).

0
source

All Articles