Java8 behavior of parametric study notes

Parameterized behavior: to help you deal with frequently changing needs of a software development model in which blocks of code can be passed as a parameter to another method, go to execute it later. At this time, the behavior of this method is based on the piece of code is parameterized.

Behavior is to allow parametric method accepts a variety of acts (or strategies) as a parameter, and used internally to perform different actions. 

Features:

1) may do "something" for each element in the list

2) do the "other thing" can be dealt with in the list

3) can do "one more thing" when it encounters an error

Example 1: Implementing selected from a list of green apples?

There are several ways to achieve:

Method 1: traverse Screening

public static List<Apple> filterGreenApples(List<Apple> list) { 

    List<Apple> result = new ArrayList<>();

    for(Apple apple: list){

        if("green".equals(apple.getColor()) result.add(apple);

    }

    return result;

}

This way you can achieve green apple screening requirements, but if you want to filter more colors Apple can not meet demand, and must be copied more filterGreenApples method or add various conditions to determine if the body of the loop to solve, brought the problem is that code duplication and reuse rate is low and difficult to maintain.

Second way: as the color parameters, to adapt to different color

public static List<Apple> filterApplesByColor(List<Apple> list, String color) {

    List<Apple> result = new ArrayList<>();

    for (Apple apple: list){

        if (apple.getColor().equals(color)) result.add(apple); 

    }

    return result;

}

This way you can solve the problem of the color filter, but if you want to filter by weight of how to handle it? If the above method to copy a changed filter by weight, it will bring duplication of code, if you want to change the traversal improve performance, you must change all the way too costly.

Three ways: trying to do the screening for each attribute you can think of

public static List<Apple> filterApples(List<Apple> list, String color, int weight, boolean flag) {

    List<Apple> result = new ArrayList<>();

    for (Apple apple: list){

        if ((flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight))

            result.add(apple);

    }

    return result;

}

Although this approach can solve these needs, but the implementation is very poor, not recommended. If the combination of attributes or more complex queries, there will be multiple duplicate filter method or very complex parameters, it will be very difficult to maintain them.

Four ways, the choice of standard modeling, based on abstract criteria to filter (strategy pattern)

You need a better argument than adding a lot of ways to respond to changing needs, one possible solution is to model your selection criteria: such as to return a boolean value based on certain attributes of Apple. We call it a predicate (that is, a boolean function that returns a value).

Defining an interface to model selection criteria:

public interface ApplePredicate{

    boolean test (Apple apple);

}

At this point you can achieve multiple ApplePredicate representatives of different selection criteria, such as:

public class AppleHeavyWeightPredicate implements ApplePredicate{

    public boolean test (Apple apple) {return apple.getWeight ()> 150;} // Filter Weight

}

public class AppleGreenColorPredicate implements ApplePredicate{

    public boolean test(Apple apple){return "green".equals(apple.getColor());} //筛选颜色

}

Use ApplePredicate improved screening methods:

public static List<Apple> filterApples(List<Apple> list, ApplePredicate p){

    List<Apple> result = new ArrayList<>();

    for(Apple apple: inventory){

        if (p.test (apple)) result.add (apple); // verb object encapsulates the test conditions Apple

    }

    return result;

}

At this time, the code looks more concise and clear and easy to use and flexible, and can easily cope with different needs change depending on the conditions. For example: to find all the weight of more than 150 grams of red apple.

public class AppleRedAndHeavyPredicate implements ApplePredicate{

    public boolean test(Apple apple){

        return "red".equals(apple.getColor()) && apple.getWeight() > 150;

    }

}

List<Apple> redAndHeavyApples = filterApples(inventory, new AppleRedAndHeavyPredicate());

FilterApples method depends on the behavior of code that you pass through ApplePredicate object, that the behavior filterApples method parameterized.

17879487-94dd18f3be3fb29f.png
Parametric filterApples behavior and deliver different screening strategies

Way five or use an anonymous class

In the manner described above when you need to pass new behavior to filterApples method, you have to declare several classes implement ApplePredicate interface, and then instantiate multiple objects will only be used once ApplePredicate, make the code look more long-winded. How to improve? Java has a mechanism called an anonymous class, it allows you to simultaneously declare and instantiate a class, to help you improve the code more concise.

By creating an object to achieve ApplePredicate with anonymous classes, override screening:

List <Apple> redApples = filterApples (inventory, new ApplePredicate () {// direct inline parametric behavior of the method filterapples

    public boolean test(Apple apple){ return "red".equals(apple.getColor());}

}); 

Anonymous class disadvantages: relatively bulky, larger space, followed by the code is not easily understood;

17879487-9d599beca9d276d5.png

The answer: 5, this means that contains it Runnable, rather than outside of class MeaningOfThis.

Way six or use Lambda expressions (recommended)

Lambda expressions used to rewrite the above code:

List result = filterApples(inventory,(Apple apple) -> "red".equals(apple.getColor()));

This way the code is very simple, it looks more like a statement of the problem itself, completely solve the problem of long-winded anonymous class;

Mode 7. List the type of abstraction (Advanced)

Currently filterApples method also applies only to Apple, you can also type List further abstraction, realization deal with more problems, as follows:

public interface Predicate<T>{boolean test(T t);}

public static <T> List <T> filter (List <T> list, Predicate <T> p) {// introduced generic type parameter T

    List<T> result = new ArrayList<>();

    for(T e: list){

        if(p.test(e)) result.add(e);

    }

    return result;

}

Example 2: Comparator used to sort

In the Java 8, List comes a sort method (or Collections.sort). sort of behavior can be parameterized objects java.util.Comparator:

public interface Comparator<T> {public int compare(T o1, T o2);}

You can create an implementation of Comparator, with a sort methods exhibit different behavior. For example, you can use an anonymous class, sort the inventory in accordance with weight in ascending order:

1> Normal mode

inventory.sort(new Comparator<Apple>() {

    public int compare(Apple a1, Apple a2){

        return a1.getWeight().compareTo(a2.getWeight());

    }

});

2> Lambda way

inventory.sort( (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

Example 3: a block of code Runnable

Runnable interface represents a block of code to be executed, the code does not return any result;

public interface Runnable{public void run();}

1> Normal mode

Thread t = new Thread(new Runnable() {

    public void run(){ 

        System.out.println("Hello world");

    }

});

2> Lambda way

Thread t = new Thread(() -> System.out.println("Hello world"));

                                                                                       The above example is taken from "Java8 real"

Reproduced in: https: //www.jianshu.com/p/a8c3effa61dc

Guess you like

Origin blog.csdn.net/weixin_34236497/article/details/91095583