Java8 came out in 2014, which is a long time ago, but there are still a lot of people who haven’t used it, including my former colleagues who are not familiar with it, for a variety of reasons, maybe older programmers don’t think it’s necessary; Or it may be due to personality, refuse to accept new things, everything conservative, can use the line; It could also be that the project is so old that it is still using JDK1.7 or older that you don’t have access to java8 writing and don’t need to.

Whatever the reason, when something new comes along, there is no sense of adventure, no experimenting, no thinking in terms of your own situation. If you have some basic knowledge of programming, you will understand that it is not only comfortable to write, but also can provide you with more work efficiency, so that you can have more time for paid swimming, self-improvement, and the peak of life.

Lambda expressions

A Lambda expression can be thought of as an anonymous function: it has no name, a list of arguments, a function body, a return type, and possibly a list of exceptions.

Parameters -> body

Lambda expressions :(parameters) -> expression or (parameters) -> {statements; }

Functional interface

What is a functional interface?

An interface that defines only abstract methods, like Predicate, Comparator, and Runnable. @functionalInterface All functional interfaces carry this annotation, which indicates that the interface is designed to be functional.

Behavior parameterization

The ability of a method to take multiple different behaviors as parameters and use them internally to accomplish different behaviors.

What can a functional interface do?

Lambda expressions allow you to provide implementations of abstract methods of a functional interface directly inline, and to treat the entire expression as an instance of the functional interface, that is, a Lambda is a concrete implementation of the functional interface. Functional interfaces and lambdas lead to more concise code in projects. Let’s look at some functional interfaces:

  • java.util.function.PredicateThis interface defines an abstract method of test, which takes a generic T object and returns a Boolean value. You can use this interface when you need to represent a Boolean expression involving type T.
  • java.util.function.ConsumerThis interface defines the accept abstract method, which accepts objects of the generic type T without returning them. You can use it if you need to access objects of type T and perform certain operations.
  • java.util.function.FunctionThis interface defines the apply method, which takes an object of generic T and returns an object of generic R. You can use this interface if you need to specify a Lambda to map the input object to the output object.
  • Ps: We can also define our own functional interface. This is too awkward to say, or paste some code, let everyone have a look:
@functionalInterface public interface Predicate<T> {// I just took part of the code,testJava8 is the only abstract method for this interface. Since Java8, not only can there be abstract methods in an interface, but also implementation methods can exist, using default and static. booleantest(T t);
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
Copy the code

Let’s see how Lambda and functional interfaces work happily together: First define a method that takes a functional interface as an argument:

private static <T> List<T> filter(List<T> list, Predicate<T> predicate) {
    List<T> result = new ArrayList<>();
    for (T e : list) {
        if (predicate.test(e)) {
            result.add(e);
        }
    }
    return result;
}
Copy the code

Then you can write:

List<Apple> apples = filter(list, (Apple apple) -> "red".equals(apple.getColor()));
Copy the code

Above, the filter method takes a set of generic types and Predicate, and the abstract methods in this functional interface take an object and return a Boolean, so Lambda can be written as an entity object Apple, and the body is an expression that returns a Boolean, Passing this Lambda as an argument to the filter() method is also a behavior parameterization feature of java8. So we can pick out the red apples. Using generics means we can reuse this code to do something else, pick out what you want:

List<String> stringList = filter(strList, StringUtils::isNoneBlank);
Copy the code

The method signature of an abstract method corresponds to the signature of a Lambda expression. If you want to apply different Lambda expressions, you need multiple functional interfaces, which I can define myself.

There are only reference types or primitive types in Java because of the way generics are implemented internally. Therefore, in Java there is a mechanism for converting primitive types to their corresponding reference types called boxing. The opposite operation, which converts a reference type to the corresponding primitive type, is called unboxing.

Java also has an autoboxing mechanism, which means that the boxing and unboxing operations are done automatically, but this comes at a cost in terms of performance. The boxed value is essentially a wrapper around the original type and stored in the heap. As a result, the boxed value requires more memory, and additional memory is required to search for the original wrapped value.

To this end, functional interfaces in java8 provide separate interfaces, just to avoid automatic boxing and unboxing of inputs and outputs.

In general, we can see it in the name, at a glance. There will be a primitive type prefix on the original name. Like the Function interface for output parameter types. For example: ToIntFunction, IntToDoubleFunction, etc.

If necessary, we can also define your own a functional interface, please keep in mind that (T, U) – > R expression shows a simple description of a function, to the left side of the arrow represents the parameter type, the right side represents the return type, here, it represents a function with two parameters, generic T and U, respectively, the return type of R.

A functional interface does not allow checked exceptions, but there are two methods that can throw exceptions:

  • Define a functional interface of your own that throws exceptions in only abstract methods;
  • Wrap the lambda in a try-catch.

Type checking

Whereas Java7 inferred types from context through generics,lambda’s type checking is inferred from its context. Lambda finds the method signature of the method it’s in, its parameters, which they call the target type, and finds the abstract method defined in that method. What is the function descriptor that that method describes? That is, what the method looks like, what arguments it takes, and what it returns. Lambda must also conform to this. When lambda throws an exception, that abstract method must also throw an exception. With a target type, the same lambda can be associated with different functional interfaces. As long as their abstract method signatures are the same. Such as:

Callable<Integer> c = () -> 42;
PrivilegedAction<Integer> p = () -> 42;
Copy the code

Both interfaces are functions that take no arguments and return a generic T. The subject of the void compatibility rule lambda is a statement expression compatible with a function descriptor that returns void, including argument lists, such as the following:

// Predicate returns a Boolean Predicate<String> p = s -> list.add(s); // Consumer returns a void Consumer<String> b = s -> list.add(s);Copy the code

Use local variables in lambda

final int local_value = 44;
Consumer<String> stringConsumer = (String s) -> {
            int new_local_value = s.length() + local_value;
        };
Copy the code

The use of instance and static variables is unlimited ina lambda, but only final. Assigning a value to a variable in an expression will fail compilation. Why does that happen? Because instance variables are stored in the heap and local variables are stored on the stack, lambda is in a thread. If a lambda has direct access to a local variable, the thread of the lambda may access the variable only after the thread that allocated the variable has reclaimed it. When you access a local variable, you are actually accessing its copy, not the original variable.

Method references

Method references, in which the method target entity comes before :: and the method name comes after. Like Apple::getWeight, no parentheses needed. The constructor is used to create a reference with its name and keyword new.

//Supplier is also a functional interface. The only abstract method takes no arguments and returns an object Supplier<Apple> sup = Apple::new; Apple apple = sup.get();Copy the code

But what if it has parameters?

Function<Long, Apple> fun = Apple::new; Apple apple1 = fun.apply(110L); BiFunction<Long, String, Apple> BiFunction = Apple::new; Apple biApple = biFunction.apply(3L,"red");
Copy the code

But what if there are three arguments, four arguments? We talked about how you can customize a functional interface that you want.

@FunctionalInterface
public interface AppleWithParam<T, U, V, R> {
    R apply(T t, U u, V v);
}
Copy the code

Conclusion:

  • The functional interfaces that come with java8, and the primitive type conversions of functional interfaces to avoid unboxing operations.
  • A functional interface is one that defines only an abstract method. The signature of an abstract method (called a function descriptor) describes the signature of a Lambda expression.
  • Lambda expressions can only be used where functional interfaces are accepted.
  • Interfaces can now also have default methods (that is, classes that implement interfaces that provide default methods when they do not implement methods).

The last

Only by actively embracing change can we grow faster.

If you have any objection to this article or have any good suggestions, you can add me as a friend (contact the author on the background of the official account) or leave a comment in the comments section below. I hope this article can help you break through the difficulties and overcome the waves.

I will continue to share things like this. Your attention, forwarding and watching are the biggest support for me. Thank you.