This article is participating in “Java Theme Month – Java Development in Action”, see the activity link for details

The opening

This is the third day of my participation in Gwen Challenge

JDK8 is known for its Lambda feature, which is used by many people, such as Stream, but is simple to use, such as calling the Stream API, but does not define its own function interface or API. Today, we will use several examples to improve the use of Java functional programming.

Case presentation

Function Interface Description

interface The input parameters The return type instructions
UnaryOperator T T Unary function with the same input and output types
Predicate T boolean assertions
Consumer T / Consume a piece of data with only input and no output
Function<T,R> T R Input T returns R, with input and output
Supplier / T Provide a piece of data with no input but only output
BiFunction<T,U,R> (T,U) R Two input parameters
BiPredicate<L, R> (L,R) boolean Two input parameters
BiConsumer<T, U> (T,U) void Two input parameters
BinaryOperator (T,T) T A binary function of the same input and output type

Case a

Function<Integer, Integer> times2 = e -> e * 2;
Function<Integer, Integer> squared = e -> e * e;
// The argument is executed before the caller
/* * 1. 4 * 4 = 16 16 * 2 = 32 */
System.out.println("result: " + times2.compose(squared).apply(4)); / / 32
Function 8 * 8 = 64 */
System.out.println("result: " + times2.andThen(squared).apply(4)); / / 64

Copy the code

These two methods,andThenAfter the Function outside is called,composeCall before the outside Function executes.

Case 2

@Test
public void test2(a){
    // Add 3 numbers
    Function<Integer, Function<Integer, IntFunction<Integer>>> addfun3 = x -> y -> z -> x + y + z ;
    // Add 7 numbers
    Function<Integer,
            Function<Integer,
                    Function<Integer,
                            Function<Integer,
                                    Function<Integer,
                                            Function<Integer, IntFunction<Integer>>>>>>>
            addfun7 = x -> y -> z -> a -> c -> b -> d -> x + y + z + a + c + b + d;
    / / 1 + 2 + 3
    Integer sum = addfun3.apply(1).apply(2).apply(3);
    System.out.println(sum);
}
Copy the code

In this way, the cumulative effect of chained programming can be achieved

Case 3


@SafeVarargs
private static <R> Function<R, R> combineFunctions(Function<R, R>... functions) {
    return Arrays.stream(functions)
            .reduce(Function::andThen)
            .orElseThrow(() -> new IllegalArgumentException("No functions to combine"));
}

@Test
public void test3(a) {
    Function<Integer, Integer> addfun2 = x -> x * x;
    final Integer apply = combineFunctions(addfun2, addfun2).apply(2);
    System.out.println(apply);

    String str = "6";
    Function<Object, Object> splitByComma = s -> ((String) s).split(",");
    Function<Object, Object> convertToInt = tokens -> Stream.of((String[]) tokens).map(Integer::valueOf).toArray(Integer[]::new);
    Function<Object, Object> findMax = ints -> Stream.of((Integer[]) ints).max(Integer::compare).get();
    Integer max = (Integer) combineFunctions(splitByComma, convertToInt, findMax).apply(str);
    System.out.println(max);
}
Copy the code

If you want to have a method that accepts variable length Function arguments, you can use… Descriptor, where the generic

represents input and input type, used for greater compatibility
,r>

Four cases

@Test
public void test4(a){
    Function<Integer, Integer> addfun2 = x -> x * x;
    final Calculator<Integer, Integer> calculator = new Calculator<>(2);
    final Integer integer = calculator.combineFunctions(addfun2, addfun2);
    System.out.println(integer);
}

public class Calculator<R.T> {
    // The property being manipulated
    private Object input;

    public Calculator(Object input) {
        this.input = input;
    }
    // You can define the behavior of the object itself in this way
    @SuppressWarnings("unchecked")
    @SafeVarargs
    public final R combineFunctions(Function<T, T>... functions) {
        return (R) Arrays.stream(functions)
                .reduce(Function::andThen)
                .orElseThrow(() -> new IllegalArgumentException("No functions to combine")) .apply((T)input); }}Copy the code

The domain development pattern is more or less familiar. Objects can have their own behavior in addition to their own properties, and the behavior methods for objects can be defined using the functional programming paradigm.

Case 5

// BiConsumer
      
        two input parameters T, Integer
      ,>
 public static <T> Consumer<T> consumerWithIndex(BiConsumer<T, Integer> consumer) {
    class Obj {
        int i;
    }
    // will only be called once, see java.lang.Iterable#forEach
    Obj obj = new Obj();
    // Return the Consumer function
    return t -> {
        int index = obj.i++;
        Println ("list[" + index + "]=" + item) to consume the specified generic data.
        consumer.accept(t, index);
    };
}

@Test
public void test5(a){
    val list = Arrays.asList("Hi"."I"."am"."Henry.Yao");
    // 2 elements in a group
    val partition = Lists.partition(list, 2);
    partition.forEach(LambdaUtils.consumerWithIndex((item, index) -> {
        System.out.println("list[" + index + "] =" + item);
    }));
}
Copy the code

Java8 forEach() loops through objects, but there is no way to get the index subscript. For this case, you can declare a functional method to do so. The final writing form is similar to Scala, JS forEach syntax, very useful!

java.lang.Iterable#forEach

// Action: is a Consumer function
default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        /* The Consumer function is looped, and consumerWithIndex returns the Consumer function as t -> {int index = obj.i++; consumer.accept(t, index); } Obj Obj = new Obj() will only be called once, so you don't have to worry about new Obj not reset I to 0, which won't happen */consumer.accept(t, index); } action.accept(t); }}Copy the code

The above is just to expand the idea, more interesting and useful writing methods, we still need to explore and create, if you have a new and interesting functional method or tool class, welcome to the comment section to share, we make progress together.

👍 ❤️ Don’t get lost

The article continues to update every week, you can search wechat “ten minutes to learn programming” the first time to read and urge more, if this article is not bad, feel something if you support and recognition, is the biggest power of my creation, we will see the next article!