Monday, February 27, 2023

More Java 8 revisited: lambda and java.util.function things

Java 8 has more functional programming stuff

import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Consumer;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Test2 {

    // provide 1 abstract method, (the follow annotation is optional)
    @FunctionalInterface
    interface MyFunctionalInterface {
        String doSomeWork(String str);
    }

    // Optional
    public static void myMethodWithOptionalParam(Optional  param) {
        if (!param.isPresent()) System.out.println("You didn't give me a parameter");
        System.out.println("Hey the length is: " + param.orElse("").length());

    }

    public static void main(String arg[]) {


        // Functional Interface
        MyFunctionalInterface myFunctionalInterface = (s -> "hey my friend:" + s);
        System.out.println(myFunctionalInterface.doSomeWork("Johnny"));

        // Function andThen and compose
        Function  myFunction = s -> "take an s and return {" + s + "}";
        Function  myFunction2 = s -> "take another s and return (" + s + ")";
        myFunction = myFunction.andThen(myFunction2);
        System.out.println(myFunction.apply("foo"));

        // f(x) = x/2
        // g(x) = 3x
        // f o g (x) = 3*x/2

        Function  f = x -> x / 2.0;
        Function  g = x -> 3 * x;
        Function  fog = f.compose(g);
        System.out.println(fog.apply(5.0)); // f(g(5))=15/2=7.5

        // func is a function R2 -> R
        BiFunction < Double, Double, Double > hyp = (x, y) -> Math.sqrt(x * x + y * y);
        System.out.println("hypontenuse: " + hyp.apply(3d, 4d));

        // Predicate
        List < String > names = Arrays.asList(
            "Ryu", "Ken", "Blanka", "Bison", "Balrog");

        Predicate  p = (s) -> s.startsWith("B"); // has a test operation

        // Iterate through the list
        for (String st: names) {
            // call the test method
            if (p.test(st))
                System.out.println(st);
        }

        // Consumer has "accept" and can be combined with "andThen"
        Consumer sayHi = (x) -> System.out.println("Hello there: " + x.toLowerCase());
        Consumer sayBye = (x) -> System.out.println("bye now: " + x.toLowerCase());
        sayHi.andThen(sayBye).accept("my friend");

        myMethodWithOptionalParam(Optional.ofNullable("hello world"));
        myMethodWithOptionalParam(Optional.ofNullable(null));
        // myMethodWithOptionalParam(null); won't compile

    }

}
Output
hey my friend:Johnny
take another s and return (take an s and return {foo})
7.5
hypontenuse: 5.0
Blanka
Bison
Balrog
Hello there: my friend
bye now: my friend
Hey the length is: 11
You didn't give me a parameter
Hey the length is: 0

Java 8 Streams revisited

Java 8 has been around for a long time now and its Streams was one of its main new feature, but I doubt too many people actually make a lot of use of it. These can be powerful one liners that let you combine operations.
  List  myList = Arrays.asList(4,56,1,55,12,46);
  System.out.println("original list: "+myList);

  List myListFiltered = myList.stream().filter( n -> n%2 ==0).collect(Collectors.toList());
  System.out.println("even filter: "+myListFiltered);

  long countEven = myList.stream().filter(n -> n %2 ==0).count();
  System.out.println("count of even: "+countEven);

  System.out.println("max: "+  myList.stream().max(Integer::compare).get());
  System.out.println("avg: "+  myList.stream().mapToInt(Integer::intValue).average().getAsDouble());
  System.out.println("sum: "+  myList.stream().mapToInt(i->i).sum());
  System.out.println("sorted: "+myList.stream().sorted().collect(Collectors.toList()));


  List names  = Arrays.asList("ryu","ken", "guile", "chun li", "ryu", "ken");
  System.out.println("some names: "+names);
  List upper = names.stream().map(String::toUpperCase).distinct().sorted().collect(Collectors.toList());
  System.out.println("Sorted and upper and distinct: "+upper);
  
Output
  original list: [4, 56, 1, 55, 12, 46]
even filter: [4, 56, 12, 46]
count of even: 4
max: 56
avg: 29.0
sum: 174
sorted: [1, 4, 12, 46, 55, 56]
some names: [ryu, ken, guile, chun li, ryu, ken]
Sorted and upper and distinct: [CHUN LI, GUILE, KEN, RYU]