Skip to content

mtumilowicz/java11-lambda-patterns

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

java11-lambda-patterns

Functional programming patterns in java.

Reference: https://www.youtube.com/watch?v=YnzisJh-ZNI
Reference: https://www.youtube.com/watch?v=e4MT_OguDKg&index=146
Reference: https://www.amazon.com/Modern-Java-Action-functional-programming/dp/1617293563

introduction

This repo is a mix of functional design patterns that we have seen in books or on the internet.

project description

  1. try to design you API in a composable way (package: composable)
    class ShoppingAPI {
        static Function<List<Item>, Cart> buy() {
            return Cart::new;
        }
    
        static Function<Cart, Order> order() {
            return Order::new;
        }
    
        static Function<Order, Delivery> deliver() {
            return Delivery::new;
        }
    
        static Function<List<Item>, Delivery> oneClickBuy() {
            return buy()
                    .andThen(order())
                    .andThen(deliver());
        }
    }
    
    • other used classes are as simple as they can be:
      @Value
      class Cart {
          ImmutableList<Item> items;
      
          Cart(List<Item> items) {
              this.items = ImmutableList.copyOf(items);
          }
      }
      
      @Value
      class Delivery {
          Order order;
      }
      
      @Value
      class Item {
          int id;
      }
      
      @Value
      class Order {
          Cart cart;
      }
      
  2. it's often helpful to use currying(https://github.com/mtumilowicz/groovy-closure-currying) and functional interfaces to design API
    @FunctionalInterface
    interface CurrableDoubleBinaryOperator extends DoubleBinaryOperator {
    
        default DoubleUnaryOperator rate(double u) {
            return t -> applyAsDouble(t, u);
        }
    }
    
    then we can easily implement conversion classes
    class RateConverter implements CurrableDoubleBinaryOperator {
    
        @Override
        public double applyAsDouble(double value, double rate) {
            return value * rate;
        }
    
        static DoubleUnaryOperator milesToKmConverter() {
            return new RateConverter().rate(1.609);
        }
    
        static DoubleUnaryOperator celsiusToFahrenheitConverter() {
            return new RateConverter().rate(1.8).andThen(x -> x + 32);
        }
    }
    
  3. use tuples and know the stream API
    @Value
    @Builder
    public class Customer {
        ImmutableList<Order> orders;
        ImmutableList<Expense> expenses;
        
        // ... methods
    }
    
    @Value
    @Builder
    class Expense {
        Year year;
        ImmutableSet<String> tags;
    
        Stream<String> getTagsStream() {
            return SetUtils.emptyIfNull(tags).stream();
        }
    }
    
    and we want to:
    • find order with max price
      Optional<Order> findOrderWithMaxPrice() {
          return ListUtils.emptyIfNull(orders).stream()
                  .filter(Order::hasPrice)
                  .max(comparing(Order::getPrice));
      
      }
      
    • find top3 orders by price
      Triple<Order, Order, Order> findTop3OrdersByPrice() {
          return ListUtils.emptyIfNull(orders).stream()
                  .filter(Order::hasPrice)
                  .sorted(comparing(Order::getPrice, reverseOrder()))
                  .limit(3)
                  .collect(collectingAndThen(toList(), ListToTripleConverter::convert));
      }
      
    • construct an immutable map with (key, value) = (year, tags from that year)
      ImmutableMap<Year, Set<String>> yearTagsExpensesMap() {
          return ListUtils.emptyIfNull(expenses).stream()
                  .collect(collectingAndThen(groupingBy(Expense::getYear, flatMapping(Expense::getTagsStream, toSet())),
                          ImmutableMap::copyOf)
                  );
      }
      

Releases

No releases published

Packages

No packages published