Java 8 Lambda study notes (a)

Lambda expressions have been feeling is a technique very "big up", whether it is directed at itself can shorten the amount of code to the metamorphosis of the reason, or want the tool loaded to force artifact (kidding!) Brought as they are well worth learn wave.

well, let's get back to business! Lambda expressions are nothing more than the following format:

(parameters) -> expression    或      (parameters) ->{ statements; }

Syntax and in fact the same as the traditional method, the arrow on the left is a list of parameters, of course, may be empty; the right arrow is an expression or a code segment. Has launched a lambda expression, is to allow you to replace the function of the interface by the expression.

Special attention is required, the use of lambda expressions is a prerequisite, and that is only a function of interface methods to use lambda as a method when it is called. What does that mean specifically? First, look at what is the function interface?

In fact, the function interface is essentially an interface, but it is a special interface: SAM type of interface (Single Method, the Abstract) . In other words, the interface is only an abstract method, and no more, nor less. You can have static methods and the default method, because both methods are already implemented a. At the same time, this must not be an abstract method with the same name in the Object class method. Java8 new feature provides a function interface, better support for functional programming. (Specific knowledge of the function interface can reference another blog Java 8 functions and interfaces Lambda study notes (b) )

 

The following from the simple to the complex process to systematically learn about lambda expressions, hoping to uncover abnormal to me that the veil of mystery!

First, a simple example is the lambda expression, can deepen understanding of its concepts through these small chestnuts.

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

To the third example, we try to achieve it, the code is as follows:

package com.wjb.lambda;
/**
 * 函数式接口:
 * 		1.只能有一个抽象方法
		2.可以有静态方法和默认方法,因为这两种方法都是已经实现的了
		3.这个抽象方法一定不能跟Object类中的方法同名。
 * @author Administrator
 *
 */
@FunctionalInterface
interface Fun{
	//只设置一个抽象方法 ------可以正常运行
	abstract int spend(int remaining,int money);
	
	//加入静态方法和默认方法 ----可以正常运行
	static void staticMethod() {
		System.out.println("There is a static method!");
	}
	default void defaultMethod() {
		System.out.println("There is a default method!");
	}
	
	//设置Object中可以重写的抽象方法 ----编译报错
//	abstract boolean equals(Object obj);
	
}
public class FunInterface{
	public static void main(String[] args) {
		Fun fun = (a,b) -> a-b;
		System.out.println(fun.spend(100, 5));
	}
}

It would appear, lambda expression is really very simple.

Below, we take a look at the scene used lambda expressions:

1. list iterator

For each element of a list operation, as when not using a Lambda expression:

List<Integer> list = Arrays.asList(1,2,3,4,5);
for (Integer integer : list) {
	System.out.println(list);
}

Lambda expressions using the words is how it?

List<Integer> list = Arrays.asList(1,2,3,4,5);
list.forEach((integer2) -> System.out.println(integer2));

Line to get! However, note that, foreach java 8 proposed method is to realize its underlying accept method Consumer interface, so you can use lambda expressions as parameters.

If you only need a single function call list elements for processing, you can use a more compact  方法引用 instead of Lambda expressions:

list.forEach(System.out::println);

Here the method references belong to extended, interested can look at this blog  Java 8 reference method

Here are some real-development scenarios you might encounter, take a look at the lambda expression is really amazing:

(1) For example: List object to obtain a new individual fields from List <Object> object list,

When we get Id from the list of all users List <User> userList and form a new List how to do, unusual ways to achieve but too complicated

List<Long> userIdList = userList.stream.map(User::getUserId).collect(Collectors.toList());

 A very important feature of java 8 Stream is proposed, the details can see  Java 8 Stream study notes 

(2) Modify List <User> value in a field object userList

List<User> userList;//获取所有用户的Id列表
userList.foreach(User -> User.setUserId(User.getUserId+1));

(3) modify the plurality of parameter values ​​List <User> userList in

userList.foreach((x) -> {x.setUserId(0L); x.setUserName(""); x.setUserSex(0);})

(4) List filtered value

List<String> list
//过滤null值
list.stream.filter(x -> x != null).collect(Collectors.toList());
//过滤特定值(包括空字符串"")
list.stream.filter(x -> !"str".equals(x)).collect(Collectors.toList());

(5) a comma delimited string rotation List <Long>

List<Long> listIds = Arrays.asList(ids.split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());

Code function is transferred after the first list of strings is cut into an array, then when traversing the list box is removed and transferred to a Long types of elements, and finally transferred to the new list.

(6) List transfected Map (assuming a list List <FlowNodeTimeoutRuleUser> userList)

//1.List对象中两个字段对应
Map<Long, String> userMap1 = userList.stream().collect(Collectors.toMap(FlowNodeTimeoutRuleUser::getUserId, FlowNodeTimeoutRuleUser::getUserName));
//2.List对象中字段和对象本体对应
Map<Long, String> userMap2 = userList.stream().collect(Collectors.toMap(FlowNodeTimeoutRuleUser::getUserId, x -> x));
//本体表达式可以用lambda表达式x->x 也可以使用接口Function.identity()
Map<Long, String> userMap3 = userList.stream().collect(Collectors.toMap(FlowNodeTimeoutRuleUser::getUserId, Function.identity()));
//3. List对象中key字段重复导致错误,增加一个lambda表达式(key1, key2) -> key2,后者覆盖前者解决key重复问题
Map<Long, String> userMap4 = userList.stream().collect(Collectors.toMap(FlowNodeTimeoutRuleUser::getUserId, Function.identity(), (key1, key2) -> key2));

 Do not understand a particular method can view the source code to know.

(7) List the number of repeats statistics:

List<Integer> list = Arrays.asList(1,1,2,5,2,3,4,5);
//统计List中重复数量
Map<Integer,Long> map = list.stream().collect(Collectors.groupingBy(x -> x,Collectors.counting()));

 In which the lambda expression x-> x is a list element itself.

(8) List deduplication Found:

List.stream().distinct().collect(Collectors.toList());

 (9) The value of the object property list value deduplication

List<Person> unique = persons.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new)
);

(10) List sorted in ascending order

List<User> userList;
userList.sort((User u1, User u2) -> u1.getAge().compareTo(u2.getAge()));

2. Event Listeners

Do not use Lambda expressions:

button.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        //handle the event
    }
});

Here is the realization of an anonymous inner class methods used.

Lambda expressions use, when you need to write multiple statements surrounded by braces:

button.addActionListener(e -> {
    //handle the event
});

3. Predicate Interface

Predicate java.util.function package for the interface can be easily filtered. If you need to filter the plurality of objects and performs the same processing logic, then these same operations can be packaged into filter method, filter criteria provided by the caller, for reuse.

Predicate interfaces is not used, for each object, requires the preparation of filters and processing logic:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> words = Arrays.asList("a", "ab", "abc");

numbers.forEach(x -> {
    if (x % 2 == 0) {
        //process logic
    }
})
words.forEach(x -> {
    if (x.length() > 1) {
        //process logic
    }
})

Predicate interfaces use the same filter processing logic to process the package, is called repeatedly:

public static void main(String[] args) {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    List<String> words = Arrays.asList("a", "ab", "abc");

    filter(numbers, x -> (int)x % 2 == 0);
    filter(words, x -> ((String)x).length() > 1);
}

public static void filter(List list, Predicate condition) {
    list.forEach(x -> {
        if (condition.test(x)) {
            //process logic
        }
    })
}

filter method may also be written as:

public static void filter(List list, Predicate condition) {
    list.stream().filter(x -> condition.test(x)).forEach(x -> {
        //process logic
    })
}

 

4.Map map

Stream object map using the method of mapping the original list via Lambda expressions is another list, and converted back to collect List by type of method:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> mapped = numbers.stream().map(x -> x * 2).collect(Collectors.toList());
mapped.forEach(System.out::println);

After the list of elements multiplied by 2 to assign a new list, implemented Stream ways, a lot less code.

5. Reduce the polymerization

reduce operation, the polymerization is performed by a binary operation for all of the elements, to obtain a final result. For example, addition polymerization of the list, all of the elements in the list is accumulated to obtain the sum.

Thus, we can provide a receiving two parameters of a Lambda expression reduce, this expression is equivalent to a binary operation:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce((x, y) -> x + y).get();
System.out.println(sum);

Stream is a way to achieve!

6. Instead of Runnable

This is especially common scenarios below to create a thread, for example, unusual Runnable class using the code below:

Runnable r = new Runnable() {
    @Override
    public void run() {
        //to do something
    }
};
Thread t = new Thread(r);
t.start();

Use Lambda Expressions:

Runnable r = () -> {
    //to do something
};
Thread t = new Thread(r);
t.start();

Or use a more compact form:

new Thread(()->System.out.println("run thread...")).start();

references

Common scenarios Java Lambda expressions

The use of Java in Lambda expressions

Examples lambda expression often used in work

Published 61 original articles · won praise 9 · views 30000 +

Guess you like

Origin blog.csdn.net/qq_33204444/article/details/104993147