The biggest feature of Java 8: Lambda expressions

Posted by teejayuu on Thu, 25 Jul 2019 09:09:24 +0200

I. Introduction

The biggest feature of Java 8 is the introduction of Lambda expressions, i.e. functional programming, which can transfer behavior. The conclusion is: using immutable values and functions, functions process immutable values and map them to another value.

2. Important Functional Interfaces in java

1. What is a functional interface?

Function interfaces are interfaces that have only one abstract method and are used as types of Lambda expressions. Using the @FunctionalInterface annotation to modify a class, the compiler detects whether the class has only one abstract method or interface, otherwise it will report an error. There can be multiple default methods, static methods.

1.1 Java 8 comes with common functional interfaces.

 

 

public class Test {    public static void main(String[] args) {        Predicate<Integer> predicate = x -> x > 185;        Student student = new Student("9 Loong", 23, 175);        System.out.println(            "9 Is the Dragon taller than 185? :" + predicate.test(student.getStature()));
        Consumer<String> consumer = System.out::println;        consumer.accept("My destiny is beyond my control.");
        Function<Student, String> function = Student::getName;        String name = function.apply(student);        System.out.println(name);
        Supplier<Integer> supplier =             () -> Integer.valueOf(BigDecimal.TEN.toString());        System.out.println(supplier.get());
        UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;        Boolean apply2 = unaryOperator.apply(true);        System.out.println(apply2);
        BinaryOperator<Integer> operator = (x, y) -> x * y;        Integer integer = operator.apply(2, 3);        System.out.println(integer);
        test(() -> "I am a demonstrative functional interface");    }
    /**     * Demonstrate the use of custom functional interfaces     *     * @param worker     */    public static void test(Worker worker) {        String work = worker.work();        System.out.println(work);    }
    public interface Worker {        String work();    }}//Is dragon 9 taller than 185? false://My destiny is beyond my control.//9 Dragons//10//false//6//I am a demonstrative functional interface

 

The above demonstrates the use of lambda interface and the customization of a functional interface and its use. Next, let's see how Java 8 can effectively help us deal with collections by encapsulating functional interfaces into streams.

Note: In the Student::getName example, this way of writing lambda expressions is called method reference. The format is ClassNmae::methodName. Isn't it amazing that Java 8 is so fascinating?

Example: All the examples in this article are based on the following three classes. Outstanding Class: Class; Student: Student; Speciality Enum: Speciality.

 

 

1.2 Inert Valuation and Early Valuation

Inert evaluation: Only Stream is described, and the result of the operation is Stream. Such an operation is called inert evaluation. Inert evaluation can be used as a chain like the builder model, and the final result can be obtained by using it as early as possible.

Early evaluation: Getting the final result instead of Stream is called early evaluation.

2. Common stream

2.1 collect(Collectors.toList())

Convert the stream to a list. There are also toSet(), toMap(), and so on. Evaluate early.

public class TestCase {    public static void main(String[] args) {        List<Student> studentList = Stream.of(new Student("Monkey D Luffy", 22, 175),                new Student("Red hair", 40, 180),                new Student("White beard", 50, 185)).collect(Collectors.toList());        System.out.println(studentList);    }}//Output results//[Student{name='Luffy', age=22, stature=175, specialities=null}, //Student{name='Red hair', age=40, stature=180, specialities=null}, //Student{name='white beard', age=50, stature=185, specialities=null}]

 

2.2 filter

As the name implies, it plays the role of filtering and screening. Inside is the Predicate interface. Inert evaluation.

 

 

For example, we screened out students whose birth height is less than 180.

public class TestCase {    public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
        List<Student> list = students.stream()            .filter(stu -> stu.getStature() < 180)            .collect(Collectors.toList());        System.out.println(list);    }}//Output results//[Student{name='Luffy', age=22, stature=175, specialities=null}]

 

2.3 map

Conversion function, the internal is the Function interface. Inert evaluation

 

 

public class TestCase {    public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
        List<String> names = students.stream().map(student -> student.getName())                .collect(Collectors.toList());        System.out.println(names);    }}//Output results//[Lufei, red hair, white beard]

 

In the example, the student object is converted to a String object to get the name of the student.

2.4 flatMap

Merge multiple Streams into one Stream. Inert evaluation


 

 

public class TestCase {            public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
        List<Student> studentList = Stream.of(students,                asList(new Student("ACE", 25, 183),                        new Student("Rayleigh", 48, 176)))                .flatMap(students1 -> students1.stream()).collect(Collectors.toList());        System.out.println(studentList);    }}//Output results//[Student{name='Luffy', age=22, stature=175, specialities=null}, //Student{name='Red hair', age=40, stature=180, specialities=null}, //Student{name='white beard', age=50, stature=185, specialities=null}, //Student{name='Ais', age=25, stature=183, specialities=null},//Student{name='Rayleigh', age=48, stature=176, specialities=null}]

The static method of calling Stream.of converts the two list s into Stream, and then merges the two streams into one through flatMap.

2.5 max and min

We often find the maximum or minimum value in the set, so it is very convenient to use the stream. Evaluate early.

public class TestCase {    public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
        Optional<Student> max = students.stream()            .max(Comparator.comparing(stu -> stu.getAge()));        Optional<Student> min = students.stream()            .min(Comparator.comparing(stu -> stu.getAge()));        //Judging whether there is value        if (max.isPresent()) {            System.out.println(max.get());        }        if (min.isPresent()) {            System.out.println(min.get());        }    }}//Output results//Student{name='white beard', age=50, stature=185, specialities=null}//Student{name='Luffy', age=22, stature=175, specialities=null}

 

Max and min receive a Comparator (in this case, using the static function that comes with Java 8, you only need to pass in the comparison value that you need.) And it returns an Optional object, which is a new class in Java 8, specifically designed to prevent null-triggered null pointer exceptions. You can use max.isPresent() to determine whether there is a value; you can use max.orElse(new Student()) to use a given value when the value is null; you can also use max. orElseGet () - > New Student ()); this requires passing in a lambda expression of Supplier.

2.6 count

Statistical functions are generally combined with filters, because we need to filter out the statistics can be. Eager evaluation

public class TestCase {    public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
        long count = students.stream().filter(s1 -> s1.getAge() < 45).count();        System.out.println("The number of people younger than 45 years old is:" + count);    }}//Output results//The number of people younger than 45 years old is 2.

 

2.7 reduce

reduce operations can generate a value from a set of values. The count, min, and max squares used in the above examples
Law is included in the standard library for its common use. In fact, these methods are reduce operations. Evaluate early.

 

 

public class TestCase {    public static void main(String[] args) {        Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);        System.out.println(reduce);    }}//Output results//10

 

We can see that reduce receives an accumulator with an initial value of 0 and adds the value to the accumulator in turn. The final value of the accumulator is the final result.

Advanced Collection Classes and Collectors

3.1 Conversion Value

Collector, a general structure for generating complex values from streams. Just pass it to the collect method, all
The stream can be used. Standard class libraries already provide some useful collectors, all of which are imported statically from the java.util.stream.Collectors class in the following sample code.

public class CollectorsTest {    public static void main(String[] args) {        List<Student> students1 = new ArrayList<>(3);        students1.add(new Student("Monkey D Luffy", 23, 175));        students1.add(new Student("Red hair", 40, 180));        students1.add(new Student("White beard", 50, 185));
        OutstandingClass ostClass1 = new OutstandingClass("Class one", students1);        //Duplicate students1 and remove a student        List<Student> students2 = new ArrayList<>(students1);        students2.remove(1);        OutstandingClass ostClass2 = new OutstandingClass("Class two", students2);        //Convert ostClass1, ostClass2 to Stream        Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);        OutstandingClass outstandingClass = biggestGroup(classStream);        System.out.println("The largest number of classes are:" + outstandingClass.getName());
        System.out.println("The average age of the first class is:" + averageNumberOfStudent(students1));    }
    /**     * Classes with the largest number of students     */    private static OutstandingClass biggestGroup(Stream<OutstandingClass> outstandingClasses) {        return outstandingClasses.collect(                maxBy(comparing(ostClass -> ostClass.getStudents().size())))                .orElseGet(OutstandingClass::new);    }
    /**     * Calculate average age     */    private static double averageNumberOfStudent(List<Student> students) {        return students.stream().collect(averagingInt(Student::getAge));    }}//Output results//The class with the largest number of students is Class One.//The average age of the first class is 37.666666666666664.

 

maxBy or minBy is to find the maximum and minimum.

3.2 Conversion Block

The common stream operation is to decompose it into two sets. Collectors.partitioningBy helps us to implement it and receive a Predicate functional interface.

 

 

The sample students are divided into two groups: those who can sing and those who can not.

public class PartitioningByTest {    public static void main(String[] args) {        //Eliminate the initialization of List < student > students        Map<Boolean, List<Student>> listMap = students.stream().collect(            Collectors.partitioningBy(student -> student.getSpecialities().                                      contains(SpecialityEnum.SING)));    }}

 

3.3 Data Grouping

Data grouping is a more natural way to segment data, which is different from dividing data into two parts: ture and false.
Grouping data with arbitrary values. Collectors.groupingBy receives a Function for conversion.

 

 

As shown in the figure, we use grouping by grouping them into circles, triangles and squares.

Example: Grouping students according to their first specialty

public class GroupingByTest {    public static void main(String[] args) {        //Eliminate the initialization of List < student > students         Map<SpecialityEnum, List<Student>> listMap =              students.stream().collect(             Collectors.groupingBy(student -> student.getSpecialities().get(0)));    }}
Collectors.groupingBy is the same as group by operation in SQL.

3.4 String Mosaic

What if all the students'names were stitched together? Usually you can only create a String Builder, which is circular stitching. With Stream, using Collectors.joining() is simple and easy.

public class JoiningTest {    public static void main(String[] args) {        List<Student> students = new ArrayList<>(3);        students.add(new Student("Monkey D Luffy", 22, 175));        students.add(new Student("Red hair", 40, 180));        students.add(new Student("White beard", 50, 185));
         String names = students.stream()             .map(Student::getName).collect(Collectors.joining(",","[","]"));        System.out.println(names);    }}//Output results//[Lufei, red hair, white beard]

Joining takes three parameters, the first is the delimiter, the second is the prefix, and the third is the terminator. You can also do this without passing in the parameter Collectors.joining(), which is a direct splicing.

IV. SUMMARY

This article mainly describes the commonly used methods and streams from the actual use, using java 8 can clearly express what you want to do, the code is also concise. This example is mainly for the sake of simplicity. You can use Java 8 to reconstruct your existing code and understand the mystery of lambda. Stream described in this article will play a greater role in combination. Chain call is very attractive. Do it according to your own business.

Author: Nine Dragons
https://juejin.im/post/5ce66801e51d455d850d3a4a

Topics: Java Lambda Programming less