Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Java 8 Functional Programming for Groovy Develo...

Java 8 Functional Programming for Groovy Developers

An introduction to the JDK8 functional model for Groovy developers.

John Engelman

July 31, 2015
Tweet

More Decks by John Engelman

Other Decks in Technology

Transcript

  1. public static <T> TransformablePublisher<T> stream(Publisher<T> publisher) { return Streams.transformable(subscriber ->

    require().streamSubscribe((handle) -> publisher.subscribe(new Subscriber<T>() { @Override public void onSubscribe(final Subscription subscription) { handle.event(() -> subscriber.onSubscribe(subscription) ); } @Override public void onNext(final T element) { handle.event(() -> subscriber.onNext(element)); } @Override public void onComplete() { handle.complete(subscriber::onComplete); } @Override public void onError(final Throwable cause) { handle.complete(() -> subscriber.onError(cause)); } }) )); }
  2. JDK8 Functional Interfaces Conceptually, a functional interface has exactly one

    abstract method. - https://docs.oracle.com/javase/8/docs/api/java/ lang/FunctionalInterface.html
  3. Supplier<Foo> supply() { return (() -> { return new Foo();

    }); } lambda expression parameters list body
  4. Supplier<Foo> supply() { return (() -> new Foo()); } implicit

    return where have we seen that before?
  5. Supplier<Foo> supply() { return { new Foo() } } Supplier<Foo>

    supply() { //http://mrhaki.blogspot.com/2015/03/groovy-goodness- use-constructor-as.htm Foo.metaClass.&invokeConstructor }
  6. Consumer<Foo> consume() { return { val -> println val.name }

    } Consumer<Foo> consumeMethod() { this.&println }
  7. Function<Foo, Bar> convert() { return (foo -> { return new

    Bar(foo.name); }); } Function<Foo, Bar> convertMethod() { return Bar::new; }
  8. Function<Foo, Bar> convert() { return { foo -> new Bar(foo.name)

    } } Function<Foo, Bar> convertMethod() { Bar.metaClass.&invokeConstructor }
  9. public interface BiConsumer<T, U> { void accept(T t, U u);

    } public interface BiFunction<T, U, R> { R apply(T t, U u); }
  10. • BiConsumer<T, U> • BiFunction<T, U, R> • BinaryOperator<T> •

    BiPredicate<T, U> • BooleanSupplier • Consumer<T> • DoubleBinaryOperator • DoubleConsumer • DoubleFunction<R> • DoublePredicate • DoubleSupplier • DoubleToIntFunction • DoubleToLongFunction • DoubleUnaryOperator • Function<T, R> • IntBinaryOperator • IntConsumer • IntFunction<R> • IntPredicate • IntSupplier • IntToDoubleFunction • IntToLongFunction • IntUnaryOperator • LongBinaryOperator • LongConsumer • LongFunction<R> • LongPredicate • LongSupplier • LongToDoubleFunction • LongToIntFunction • LongUnaryOperator • ObjDoubleConsumer<T> • ObjIntConsumer<T> • ObjLongConsumer<T> • Predicate<T> • Supplier<T> • ToDoubleBiFunction<T, U> • ToDoubleFunction<T> • ToIntBitFunction<T, U> • ToIntFunction<T> • ToLongBiFunction<T, U> • ToLongFunction<T> • UnaryOperator<T> Java • Closure Groovy
  11. List<Foo> filter(List<Foo> foos) { return foos.stream() .filter(foo -> foo.name.equals(“bar") ).collect(Collectors.toList());

    } List<Bar> map(List<Foo> foos) { return foos.stream() .map(Bar::new).collect(Collectors.toList()); } List<Foo> distinct(List<Foo> foos) { return foos.stream().distinct().collect(Collectors.toList()); }
  12. List<Foo> filter(List<Foo> foos) { foos.findAll { foo -> foo.name ==

    'bar' } } List<Bar> map(List<Foo> foos) { foos.collect { new Bar(foo) } } List<Foo> distinct(List<Foo> foos) { foos.unique() }
  13. public static <T> TransformablePublisher<T> stream(Publisher<T> publisher) { return Streams.transformable(subscriber ->

    require().streamSubscribe((handle) -> publisher.subscribe(new Subscriber<T>() { @Override public void onSubscribe(final Subscription subscription) { handle.event(() -> subscriber.onSubscribe(subscription) ); } @Override public void onNext(final T element) { handle.event(() -> subscriber.onNext(element)); } @Override public void onComplete() { handle.complete(subscriber::onComplete); } @Override public void onError(final Throwable cause) { handle.complete(() -> subscriber.onError(cause)); } }) )); }
  14. public static <T> TransformablePublisher<T> stream(Publisher<T> publisher) { return Streams.transformable {

    subscriber -> require().streamSubscribe { handle -> publisher.subscribe(new Subscriber<T>() { @Override public void onSubscribe(final Subscription subscription) { handle.event { subscriber.onSubscribe(subscription) } } @Override public void onNext(final T element) { handle.event { subscriber.onNext(element) } } @Override public void onComplete() { handle.complete(subscriber.&onComplete) } @Override public void onError(final Throwable cause) { handle.complete { subscriber.onError(cause) } } }) } } }
  15. Default Interface Methods • Game changer public interface Baz {

    String getName(); default Bar bar() { return new Bar(this); } } Bar interfaceMethod(Baz baz) { return baz.bar(); } Bar useInterface() { return interfaceMethod(() -> "John"); } becomes a Supplier<String> lambda implicitly coerced to interface
  16. Default Interface Methods • Not directly* supported in Groovy *

    Groovy 2.3 introduced Traits which are similar