Take a quick look at jdk8

Keywords: Java Lambda Lombok jvm

You've been watching java concurrently and you've been saying a bit too much. Just relax!This time, let's briefly talk about jdk8, which has not been used for a long time and is new to us. It's interesting to look at it carefully. Let's turn our brain into an angle to write code. Because we usually write code in jdk7 now, we are all thinking about how to do this step and what to do next. But jdk8 only needs to know what to do at this step, what to do next, and the conversion of thinking is very interesting.;

First, what is called behavioral parameterization?Simply speaking, passing is a behavior, which can be imagined as passing a lambda expression, not to mention a lambda expression.

Take an example:

package com.example.demo.vo;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Apple {
    private String color;
    private int weight;

}

 

If there are many apples in a collection, we need to first filter out those that weigh more than 10, then we need to define a method like this:

static List<Apple> filterColor(List<Apple>inventory){
        List<Apple> result = Lists.newArrayList();
        for (Apple apple : inventory) {
            if (apple.getWeight()>10) {
                result.add(apple);
            }
        }
        return result;
    }

  

If one day there's a sudden change in demand and we're asked to filter out the apples that are green, then we're going to define another way:

static List<Apple> filterGreen(List<Apple>inventory){
        List<Apple> result = Lists.newArrayList();
        for (Apple apple : inventory) {
            if (Objects.equal("green", apple.getColor())) {
                result.add(apple);
            }
        }
        return result;
    }

  

If you mention a certain requirement one day again, let's just look at the differences between the two methods. In fact, on closer inspection, the red code above is not the same. Other codes are directly copied and pasted. We know that sometimes there are too many copies and pastes, you will see many duplicate codes, which is pity. Is there anything like this?A simpler way?

It's easy. Since the other parts above are the same, let's bring up the same parts as a template, so in the future we just need to pass the red part code.Simple!So the question arises again. How can I program those codes into a template?There are some functional interfaces in jdk8, one of which is Predicate. Note @FunctionalInterface translation is a functional interface.Let's just use its test method for now. You can see that this method receives a parameter and returns a boolean type. The red part of the code above essentially receives an Apple type and returns a boolean type.

 

So we can make a template like this:

static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

 

Then the question comes up again. It's made. How can I use it?Let's try using the above template to filter out the weight and color of the apple, using the Lambda expression:

    public static void main(String[] args) {
        //Assemble three apples in a collection
        List<Apple> apples = Lists.newArrayList();
        Apple apple1 = new Apple();
        apple1.setColor("red").setWeight(20);
        Apple apple2 = new Apple();
        apple2.setColor("green").setWeight(20);
        Apple apple3 = new Apple();
        apple3.setColor("black").setWeight(5);
        apples.add(apple1);
        apples.add(apple2);
        apples.add(apple3);
        
        //Screen out weight>10 Apple of,The following two styles are the same
//        List<Apple> list1 = filterApples(apples,(Apple a)->a.getWeight()>10);
        List<Apple> list1 = filterApples(apples,a->a.getWeight()>10);
        System.out.println("Apples weighing more than 10:"+list1);
        
        //Filter out the apples that are green in color, as described below
//        List<Apple> list2 = filterApples(apples,(Apple a)->Objects.equal("green", a.getColor()));
        List<Apple> list2 = filterApples(apples,a->Objects.equal("green", a.getColor()));
        System.out.println("Green apple:"+list2);
        
    }

 

Is this all right?More interesting is the flow, which can be said to have been created specifically to handle collections. In fact, the code above is still too cumbersome. You have to define a method yourself. Is there a faster and faster way to use the flow?

 //Screening apples weighing more than 10 using streaming
  List<Apple> weightApples = apples.stream().filter(a->a.getWeight()>10).collect(Collectors.toList());
  System.out.println(weightApples);
        
 //Note that each fetch of a stream is one-time, and if you want to continue with the flow if you have previously obtained the return value of the stream, you can only retrieve the stream again.Use stream to filter apples that are green
  List<Apple> greenApples = apples.stream().filter(a->Objects.equal("green", a.getColor())).collect(Collectors.toList());
  System.out.println(greenApples);

 

See no, it only takes a few lines of code to use the stream, no more defining any method, just turn the collection into a stream, call the filter method chained, pass in an action (a Lambda expression here), and then call the collect method to collect the elements in the stream;

In fact, there is nothing to optimize here. Of course, for example, every time the System.out.println (xxxx) method is really annoying, can it be erased, but the console can still print out. Of course, there is a concept called method reference, what is method reference?Even if it is a function pointer, you can think that when a class is loaded into the jvm, we only need to know the memory address of the class to know the memory address of its method (you can think of calling a static method directly with the class name plus the method name), so we can call a class in this way:Then modifying System.out.println(xxx) is System.out::printIn, the code is modified as follows, and we iterate through the two sets separately:

        //Screening apples weighing more than 10 using streaming
        apples.stream().filter(a->a.getWeight()>10).collect(Collectors.toList()).forEach(System.out::println);
        
        //Use stream to filter apples that are green
        apples.stream().filter(a->Objects.equal("green", a.getColor())).collect(Collectors.toList()).forEach(System.out::println);

  

The above method reference is only the simplest way, others will be slowly followed by time;

After a quick look at jdk8, we should get some insight into the processing of this form of set, and then we'll discuss it in sections, such as how to write Lambda expressions, what are functional interfaces, what are the operations of streams, how to use method references, and so on.These cover about 80% of jdk8, followed by jdk8's new date and time api, Optional instead of null, default methods, and so on.

Posted by Xephon on Tue, 11 Feb 2020 10:42:17 -0800