Java functional interfaces 1.1 Java8 provides common functional interfaces. 1.2 Lazy and Early Evaluation 2. Common flows 2.1 Collect (Collectors. ToList ())2.2 filter2.3 map2.4 flatMap2.5 Max and Min2.6 count2.7 3.1 Conversion to Values 3.2 Conversion to Blocks 3.3 Data Grouping 3.4 String Concatenation iv. Summary

One, the introduction

The biggest feature of java8 is the introduction of Lambda expressions, or functional programming, that can pass behavior. The summary is: using immutable values and functions, functions process immutable values and map them to another value.

Java important functional interfaces

What is a functional interface

A function interface is an interface that has only one abstract method and is used as the type of a Lambda expression. For classes decorated with the @functionalInterface annotation, the compiler checks if the class has only one abstract method or interface; otherwise, an error is reported. You can have multiple default methods, static methods.

1.1 Java8 provides common functional interfaces.
The function interface Abstract methods function parameter The return type The sample
Predicate test(T t) Judge true and false T boolean Are 9 dragons taller than 185cm?
Consumer accept(T t) News consumption T void Output a value
Function R apply(T t) Map T to R (transformation function) T R Gets the name of the student object
Supplier T get() Production of the message None T The factory method
UnaryOperator T apply(T t) One yuan operation T T Logic is not (!)
BinaryOperator apply(T t, U u) The binary operation (T, T) (T) Find the product of two numbers (*)
public class Test {

    public static void main(String[] args) {

        Predicate<Integer> predicate = x -> x > 185;

        Student student = new Student("Nine dragon".23.175);

        System.out.println(

            "Are 9 dragons taller than 185? :" + predicate.test(student.getStature()));



        Consumer<String> consumer = System.out::println;

        consumer.accept("Fate is not my destiny.");



        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'm a demo functional interface.");

    }



    / * *

* Demonstrates 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(a);

    }

}

Is the 9 dragon taller than 185? : false

// Fate is determined by me

/ / nine dragons

/ / 10

//false

/ / 6

// I am a demo functional interface

Copy the code

The above demonstrates the use of lambda interface and custom a functional interface and use. Let’s take a look at how java8’s encapsulation of functional interfaces into streams effectively helps us work with collections.

Note: This way of writing lambda expressions in the Student::getName example is called a method reference. The format is ClassNmae::methodName. Isn’t that amazing? Java8 is fascinating.

Examples: All examples in this article are based on the following three classes. OutstandingClass: class; Student b. SpecialityEnum: specialty.

1.2 Lazy evaluation and early evaluation

Lazy evaluation: An operation that describes only a Stream and results in a Stream is called lazy evaluation. Lazy evaluation can be used in a chain like the builder model, then used at the end and evaluated early to the final result.

Early evaluation: The operation of getting the final result rather than the Stream is called early evaluation.

2. Common streams

2.1 collect (Collectors. ToList ())

Convert the stream to a list. ToSet (), toMap(), etc. Evaluate early.

public class TestCase {

    public static void main(String[] args) {

        List<Student> studentList = Stream.of(new Student("The road".22.175),

                new Student("Red hair".40.180),

                new Student("White Beard".50.185)).collect(Collectors.toList());

        System.out.println(studentList);

    }

}

// Output the result

//[Student{name=' lufei3 ', age=22, typical =175, specialities=null},

/ / Student {name = 'red' age = 40, stature = 180, specialities = null},

// Child {name=' white beard ', age=50, typical =185, specialities=null}]

Copy the code
2.2 the filter

As the name suggests, plays a role in filtering. Inside is the Predicate interface. Lazy evaluation.

Let’s say we screen out students who are less than 180.

public class TestCase {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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 the result

//[Student{name=' lufei3 ', age=22, typical =175, specialities=null}]

Copy the code
2.3 the map

The transformation Function, internally, is the Function interface. Inertia is evaluated

public class TestCase {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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 the result

//[Luffy, red hair, white beard]

Copy the code

The example converts the student object to a String and gets the name of student.

2.4 flatMap

Merge multiple streams into one Stream. Inertia is evaluated

public class TestCase {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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("雷利".48.176)))

                .flatMap(students1 -> students1.stream()).collect(Collectors.toList());

        System.out.println(studentList);

    }

}

// Output the result

//[Student{name=' lufei3 ', age=22, typical =175, specialities=null},

/ / Student {name = 'red' age = 40, stature = 180, specialities = null},

// Child {name=' white beard ', age=50, typical =185, specialities=null},

// Child {name=' three ', age=25, typical =183, specialities=null},

//Student{name=' three classes ', age=48, typical =176, specialities=null}]

Copy the code

The static method of stream.of is called to convert two lists to streams, and flatMap is used to merge the two streams into one.

2.5 the Max and min

We often maximize or minimize values in collections, and it’s convenient to use streams. Evaluate early.

public class TestCase {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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()));

        // Check if there is a value

        if (max.isPresent()) {

            System.out.println(max.get());

        }

        if (min.isPresent()) {

            System.out.println(min.get());

        }

    }

}

// Output the result

// Child {name=' white beard ', age=50, typical =185, specialities=null}

//Student{name=' lufei3 ', age=22, typical =175, specialities=null}

Copy the code

Max and min receive a Comparator. (In this example, we use java8 static functions that simply pass in the comparison value.) And returns an Optional object that is a new class in java8 specifically designed to prevent null-raised null pointer exceptions. You can use max.ispresent () to determine whether there is a value; You can use max.orelse (new Student()) and use the given value when null; You can also use max.orelseget (() -> new Student()); This requires passing in a Supplier lambda expression.

2.6 the count

The statistics function is generally used in combination with filter, because we can select the required statistics first. Evaluated as early as possible

public class TestCase {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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 under 45 is:" + count);

    }

}

// Output the result

// The number of people under 45 is: 2

Copy the code
2.7 the reduce

The Reduce operation enables the generation of a value from a set of values. The count, min, and Max methods used in the above example are included in the standard library because they are commonly used. 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 the result

/ / 10

Copy the code

It can be seen that Reduce receives an accumulator with an initial value of 0, and takes out the values in turn and adds them to the accumulator. Finally, the value of the accumulator is the final result.

Advanced collection classes and collectors

3.1 Convert to a value

Collector, a generic structure that generates complex values from a stream. Simply pass it to the Collect method and all streams can use it. Standard class library has provided some useful collector, collector of the following sample code from Java. The util. Stream. The Collectors class static imports.

public class CollectorsTest {

    public static void main(String[] args) {

        List<Student> students1 = new ArrayList<>(3);

        students1.add(new Student("The road".23.175));

        students1.add(new Student("Red hair".40.180));

        students1.add(new Student("White Beard".50.185));



        OutstandingClass ostClass1 = new OutstandingClass("Class", students1);

        // copy students1 and remove a student

        List<Student> students2 = new ArrayList<>(students1);

        students2.remove(1);

        OutstandingClass ostClass2 = new OutstandingClass("Class 2", students2);

        // Convert ostClass1, ostClass2 to Stream

        Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);

        OutstandingClass outstandingClass = biggestGroup(classStream);

        System.out.println("The largest class is:" + outstandingClass.getName());



        System.out.println("The average age of class one is:" + averageNumberOfStudent(students1));

    }



    / * *

* The class 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 the average age

* /


    private static double averageNumberOfStudent(List<Student> students) {

        return students.stream().collect(averagingInt(Student::getAge));

    }

}

// Output the result

// The largest class is Class one

// The average age of class 1 is 37.6666666666664

Copy the code

MaxBy or minBy is a maximum and a minimum.

3.2 Converting to blocks

Common flow operation is to break it down into two sets, Collectors. PartitioningBy help we implemented, receives a Predicate functional interface.

The sample students were divided into two sets: those who could sing and those who could not sing.

public class PartitioningByTest {

    public static void main(String[] args) {

        // omit initialization of List students

        Map<Boolean, List<Student>> listMap = students.stream().collect(

            Collectors.partitioningBy(student -> student.getSpecialities().

                                      contains(SpecialityEnum.SING)));

    }

}

Copy the code

3.3 Data Grouping

Grouping data is a more natural way to split data. Instead of splitting data into true and false parts, you can group data with arbitrary values. GroupingBy Receives a Function for conversion.

As shown in the figure, we use groupingBy to group by circle group, triangle group and square group.

Example: Group the students according to their first strong point

public class GroupingByTest {

    public static void main(String[] args) {

        // omit initialization of List students

         Map<SpecialityEnum, List<Student>> listMap = 

             students.stream().collect(

             Collectors.groupingBy(student -> student.getSpecialities().get(0)));

    }

}

Copy the code

GroupingBy is the same as the group by operation in SQL.

3.4 String Stitching

What if you were to concatenate the names of all the students? You can usually create only one StringBuilder, loop concatenation. Using Stream, joining() is simple and easy.

public class JoiningTest {

    public static void main(String[] args) {

        List<Student> students = new ArrayList<>(3);

        students.add(new Student("The road".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 the result

//[Luffy, red hair, white beard]

Copy the code

Joining takes three parameters, the first a delimiter, the second a prefix, and the third an end. You can also pass no parameter, calculator.joining (), which is a direct joining.

Four,

This article focuses on the common methods and flows for practical use. Using java8 makes it very clear what you want to do, and the code is very concise. The purpose of this example is to keep things simple, so you can use java8 to refactor your existing code and get a feel for lambda. This article says that the Stream should be used in combination to achieve more function, chain call is fascinating, according to your business to do it.

Sorting is not easy, hope to support support.