Chapter 14 Lambda Expressions

Table of contents

Introduction to Iambda expressions

1. Functional interface

2.Iambda expression implements parameterless abstract method

3. Lambda expression implements parameterized abstract method

4. Lambda expressions use code blocks

2.Lambda expressions can change class member variables

Iambda expressions and exception handling

14.2 References to methods

Reference static method

Reference member method

reference constructor

1. Reference the parameterless constructor

2. Reference the parameterized constructor

3. Array construction method

14.2.5Fuction interface 

14.3 Stream processing

14.3.2 Optional class

14.3.3 Collectors class 

14.3.4 Data filtering 

1. filter() method

2. distinct() method 

3. Iimit() method

4. skip method 

14.3.5 Data Mapping 

14.3.6 Data search

1.allMatch() method

2.anyMatch method() method

3.noneMatch() method

4.findFirst() method

14.3.7 Data collection

1. Statistics


Introduction to Iambda expressions

  1. Lambda expressions can implement abstract methods with very little code.
  2. Lambda expressions cannot be executed independently, so they must implement a functional interface and return an object of the functional interface.
  3. The syntax of lambdab expressions is very special

Syntax format:

()-> result expression 

Parameters-> result expression

(Parameter 1, Parameter 2..., Parameter n) -> Result expression

  • Line 1 implements the parameterless method. A separate pair of parentheses indicates that the method has no parameters. The result expression on the right side of the operator indicates the return value of the method.
  • Line 2 implements a method with only one parameter. The parameters can be written in parentheses or not.
  • Line 3 implements the multi-parameter method. All parameters are written in parentheses in order, and the parentheses cannot be omitted.

lambdaExpressions can also implement complex methods, just replace the result expression on the right side of the operator with a code block

The syntax format is as follows:
()->{ Code block) Parameter-> (Code block} (Parameter 1 , parameter 2, .. parameter n)->{code block)

  • Line 1 implements the parameterless method, and the method body is the code block on the right side of the operator.
  • Line 2 implements a method with only one parameter, and the method body is the code block on the right side of the operator.
  • Line 3 implements the multi-parameter method, and the method body is the code block on the right side of the operator.

A summary of the functions of lambda expressions, the syntax is understood as:

()-& Gt; {code block}

This method is implemented according to the code like this 

Iambda expression implements functional interface

1. Functional interface

Developers can create custom functional interfaces

For example:

interface MyInterface{

        void method();

}

 If the interface contains more than one abstract method, it does not comply with the specifications of functional interfaces. Such interfaces cannot use Iambda expressions to create anonymous objects.

2.Iambda expression implements parameterless abstract method

Example 14.1

 
	interface SayHiInterface{	//例题14.1
		String say();//抽象方法接口
	}
 
 
public class NoParamterDemo {
	public static void main(String[] args) {//利用匿名内部类补全方法体
		//lambda表达式实现发招呼接口,返回抽象方法结果
		SayHiInterface pi=()->"你好啊,这是lanbda表达式";
		 System.out.print(pi.say());
	}
 
}

The running results are as follows:

3. Lambda expression implements parameterized abstract method

If there is only one parameter in the abstract method, the lambda expression can omit the parentheses

Example 14.2

interface AddInt{
	int add(int a,int b);
}
public class ParamDemo {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
/*无参数      AddInt ai1 = new AddInt() {
			public int add(int a,int b) {
			return a+b;
		}
	};
	System.out.println("匿名内部类:" + ai1.add(3,5));
	//使用Lambda表示式补全方法体
	AddInt ai2 = (a, b) ->{
		return a+b;
	};
	System.out.println("lambda表达式:" + ai2.add(3,5));
}
}*/
	AddInt np=(x,y)->x+y;		//表达式
	int result=np.add(15,26);					//调用接口方法
	System.out.println("相加结果:"+result);			//输出相加结果
	}
}

The running results are as follows:

The parameters in the lambda expression do not need to have the same names as the parameters of the abstract method, but they must be in the same order

4. Lambda expressions use code blocks

The lambda expression will automatically determine whether the return value type conforms to the definition of the abstract method

Example 14.3

interface CheckGrade{			//例题14.3
	String check(int grade);    //查询成绩结果
}
public class GradeDemo {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		CheckGrade g =(n)-> {			//lambda表达式实现代码块
			if (n>=90&& n<=100) {		//如果成绩在90~100
				return"成绩为优";			//输出成绩为优
			}else if (n>=80&& n<=90) {	//如果成绩在80~90
				return"成绩为良";			//输出成绩为良
			}else if (n>=60&& n<=80) {	//如果成绩在60~80
				return"成绩为中";			//输出成绩为中
			}else if (n>=0&& n<=60) {	//如果成绩在00~60
				return"成绩为差";			//输出成绩为差
			}else {						//其他数字不是有效成绩
				return"成绩无效";			//输出成绩无效
	}
};
	System.out.println(g.check(89));
	}
}

 The running results are as follows:

Iambda expression calls external variables 
Some of these external variables can be changed, while others cannot. For example, a lambda expression cannot change the value of a local variable, but it can change the value of a member variable (also called a class attribute) of an external class.

1.lambda expression cannot change local variables
Local variables are defined as final (static) by default in lambda expressions, that is to say, lambda expressions can only call Local variables, but their value cannot be changed.

Example 14.4

interface VariableInterface1{		//例题14.4
	void method();
}
public class VariableDemo1 {
	
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int value=100;
		VariableInterface1 v=()->{
			int num=value-90;
			value=12;
		};
	}
 
}

The running results are as follows:

2.Lambda expressions can change class member variables

Class member variables are not modified by final in lambda expressions, so lambda expressions can change their values.

Example 14.5

interface VariableInterface2{					//测试接口
	void method();								//测试方法
}
 
public class VariableDemo2 {					//测试类
	int value = 100;							//创建类成员变量
	public void action() {						//创建类成员方法
		VariableInterface2 v=()->{				//实现测试接口
			value =-12;							//更改成员变量,没提示任何错误
		};
		System.out.println("运行接口方法前value="+value);  //运行接口方法前先输出成员变量值
		v.method();										 //运行接口方法
		System.out.println("运行接口方法后value="+value); //运行接口方法后再输出成员变量值
	}
	public static void main(String[] args) {
		VariableDemo2 demo = new VariableDemo2();	//创建测试类对象
		demo.action();								//执行测试类方法
	}
 
}

The running results are as follows:

lambda expression can call and modify the value of class member variables
The lambda expression only describes how the abstract method is implemented. Before the abstract method is called, the lambda expression The code in is not executed, so the values ​​of class member variables will not change before running the abstract method.
As long as the abstract method is called, the code in the lambda expression will be executed, and the value of the class member variable will be modified.
 

Iambda expressions and exception handling

There is no syntax for throwing exceptions in lambda expressions. This is because lambda expressions will throw the original exception of the abstract method by default, and exception handling must be performed when this method is called.

Example 14.6

import java.util.Scanner;											
interface AntiaddictInterface{											//防沉迷接口
	boolean check(int age)throws UnderAgeException;						//抽象检查方法,抛出用户未成年异常
}
 
class UnderAgeException extends Exception{								//自定义未成年异常
	public UnderAgeException(String message) {							//有参构造方法
		super(message);													//调用原有父类构造方法
	}
}
 
public class ThrowExceptionDemo {										//测试类
	public static void main(String[] args) {							//主方法
		//lambda表达式创建AntiaddictInterface对象,默认抛出原有异常
		AntiaddictInterface ai =(a)->{
			if(a<18) {													//如果年龄小于18岁
				throw new UnderAgeException("未满18周岁,开启防沉迷模式!");		//抛出异常
			}else {														//否则
				return true;											//验证通过
			}
		};
		
		Scanner sc = new Scanner(System.in);							//创建控制台扫描器
		System.out.print("请输入年龄:");									//控制台提示
		int age = sc.nextInt();											//获取用户输入的年龄
		
		try {															//因为接口方法抛出异常,所以此处必须捕捉异常
			if(ai.check(age)) {											//验证年龄
				System.out.println("欢迎进入XX世界");
			}
		}catch(UnderAgeException e) {									//控制台打印异常警告
			System.out.println(e);
		}
		sc.close();														//关闭扫描器
	}
}

The running results are as follows:

14.2 References to methods

Reference static method

grammar:

Class name:: static method name 

NewOperator "::", no space in the middle, the left side represents the class name to which the method belongs, and the right side is the method name, syntax Chinese method names do not have brackets. 

Example 14.7

interface StaticMethodInterface{		//测试接口  例题14.7
	int method(int a, int b);			//抽象方法
}
public class StaticMethodDemo {
	static int add(int x,int y) {		//静态方法,返回两个参数相加的结果
		return x +y;					//返回相加结果
	}
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		StaticMethodInterface sm= StaticMethodDemo::add;	//引用StaticMethodDemo类的静态方法
		int result = sm.method(15,16);						//直接调用接口方法获取结果
		System.out.println("接口方法结果:"+result);				//输出结果
	}
 
}

The running results are as follows:

Reference member method

The left side of the operator must be an object name, not a class name.​ 

Example 14.8

import java.text.SimpleDateFormat;			//例题14.8
import java.util.Date;
interface InstanceMethodInterface{			//测试创建接口
	String method(Date date);				//带参数的抽象方法
}
public class InstanceMethodDemo {
	public String format(Date date) {		//格式化方法
		//创建日期格式化对象,并指定日期格式
		SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd");
		return sdf.format(date);			//返回格式化结果
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		InstanceMethodDemo demo = new InstanceMethodDemo();			//创建类对象
		InstanceMethodInterface im = demo::format;					//引用类对象的方法
		Date date = new Date();										//创建日期对象
		System.out.println("默认格式:"+date);							//输出日期对象默认格式
		System.out.println("接口输出的格式:"+im.method(date));			//输出经过接口方法处理过的格式
	}
 
}

The running results are as follows:

reference constructor

Iambda expressions have three syntaxes for reference construction methods, namely reference parameterless construction method, reference parameterized construction method and reference number construction method.

1. Reference the parameterless constructor

grammar:

Class name::new

Note: There are no parentheses after the new keyword, and there is no parameter definition 

Example 14.10

interface ConstructorsInterface1{								//构造方法接口
	ConstructorsDemo1 action();									//调用无参方法
}
public class ConstructorsDemo1 {								//测试类
	public ConstructorsDemo1() {								//无参构造方法
		System.out.print("无参构造方法");
	}
	public ConstructorsDemo1(int a) {							//有参构造方法
		System.out.print("有参构造方法"+ a);
	}
	public static void main(String[] args) {				
		ConstructorsInterface1 ci = ConstructorsDemo1::new;		//引用ConstructorsDemo1类的构造方法
		ci.action();											//通过无参方法创建对象
 
	}
 
}

The running results are as follows:

2. Reference the parameterized constructor

The syntax for referencing a parameterized constructor is the same as for referencing a parameterless constructor. The difference is that the abstract method of the functional interface has parameters.

Example 14.11

interface ConstructorsInterface2{								//构造方法接口
	ConstructorsDemo2 action(int i);							//调用有参方法
}
public class ConstructorsDemo2 {								//测试类
	public ConstructorsDemo2(){									//无参构造方法	
		System.out.print("调用无参构造方法");
	}
	public ConstructorsDemo2(int i) {							//有参构造方法
		System.out.println("有参构造方法,参数为:"+i);
	}
	public static void main(String[] args) {					
		ConstructorsInterface2 a = ConstructorsDemo2::new;		//引用ConstructorsDemo1类的构造方法
		ConstructorsDemo2 b = a.action(123);					//通过无参方法创建对象
	}
 
}

 The running results are as follows:

3. Array construction method

grammar;

Class name[]::new

 

14.2.5Fuction interface 

This interface has the following two generics:

T: The type being operated on can be understood as the method parameter type.
R: Operation result type, which can be understood as the return type of the method.
The Function interface is a functional interface, so it has only one abstract method, but the Function interface also provides
methods to facilitate developers to process function logic in a deeper manner.

14.3 Stream processing

Stream processing is somewhat similar to the SQL statements of a database, and can perform very complexfiltering, mapping, search and collection functions, and. The only drawback is that the code is not very readable. The amount of code is very small

Stream processing employee data

The detailed data of the employee collection is as follows

 Example 14.14

import java.util.ArrayList;
import java.util.List;
 
public class Employee {
	private String name;	//姓名
	private int age;		//年龄
	private double salary;	//工资
	private String sex;		//性别
	private String dept;	//部门
	
	public Employee(String name, int age, double salary, String sex, String dept) {
		super();
		this.name = name;
		this.age = age;
		this.salary = salary;
		this.sex = sex;
		this.dept = dept;
	}
	
	@Override
	public String toString() {
		return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + ", sex=" + sex + ", dept=" + dept
				+ "]";
	}
 
	public String getName() {
		return name;
	}
 
	public int getAge() {
		return age;
	}
 
	public double getSalary() {
		return salary;
	}
 
	public String getSex() {
		return sex;
	}
 
	public String getDept() {
		return dept;
	}
	static List<Employee> getEmpList(){
		List<Employee> list=new ArrayList<Employee>();
		list.add(new Employee("老张",40,9000,"男","运营部"));
		list.add(new Employee("小刘",24,5000,"女","开发部"));
		list.add(new Employee("大刚",32,7500,"男","销售部"));
		list.add(new Employee("翠花",28,5500,"女","销售部"));
		list.add(new Employee("小马",21,3000,"男","开发部"));
		list.add(new Employee("老王",35,6000,"女","人事部"));
		list.add(new Employee("小王",21,3000,"女","人事部"));
		return list;
	}
}
 

Methods as below:

Source——Generate ConStructor using Fields

Click Select Getters on the right 

14.3.1 Introduction to Stream interface
Stream processing interfaces are defined under the java.uil.stream package. The BaseStream interface is the most basic interface, but the most commonly used one is the Stream interface, a sub-interface of the BaseStream interface. Basically, most stream processing is implemented on the Stream interface. The Stream interface is a generic interface, so the elements operated on in the stream can be objects of any class.

The Collection interface adds two new methods that can obtain stream objects. The first method is the most commonly used and can obtain the sequence flow of the collection. The method is as follows:

Stream<E> stream(); 

 The second method can obtain the parallel stream of the collection as follows:

Stream<E> parallelstream();

Because all collection classes are subclasses of the Collection interface, such as the ArrayList class, HashSet class, etc., these classes can be stream processed. For example:

List<integer> list = new ArrayList<Integer>(); //Create a collection

Streamcinteger> s = list.stream();//Get the collection stream object

 

14.3.2 Optional class

 The Optional class is modified with final, so it cannot have subclasses. The Optional class is a class with generics, so this class can save the value of
any object.
These characteristics can be seen from the declaration code of the Optional class. Some codes in the JDK are as follows:

public final class Optional<T>{
private final T value;
} //省略其他代码

 There is a member attribute called value in the Optional class. This attribute is used to save specific values. value is modified with generics
and final, which means that an Optional object can only save one value.
The Optional class provides many methods for encapsulation, verification and obtaining values. These methods are as follows:

Example 14.15

import java.util.Optional;
 
public class OptionalDemo {
	public static void main(String[] args) {
		Optional<String>strValue = Optional.of("hello");			//创建有值对象
		boolean haveValueFlag = strValue.isPresent();				//判断对象中的值是不是空的
		System.out.println("strValue对象是否有值:"+haveValueFlag);
		if(haveValueFlag) {											//如果不是空的
			String str = strValue.get();							//获取对象中的值
			System.out.println("strValue对象的值是:"+str);
		}
		
		Optional<String> noValue = Optional.empty();				//创建空值对象
		boolean noValueFlag = noValue.isPresent();					//判断对象中的值是不是空的
		System.out.println("noValue对象是否有值:"+noValueFlag);
		if(noValueFlag) {											//如果不是空的
			String str = noValue.get();								//获取对象中的值
			System.out.println("noValue对象的值是:"+str);	
		}else {														//如果是空的
			String str = noValue.orElse("使用默认值");					//使用默认值
			System.out.println("noValue对象是:"+str);
		}
	}
 
}

 The running results are as follows:

14.3.3 Collectors class 

This class provides many practical data processing methods, as follows:

14.3.4 Data filtering 

Data filtering is to filter out the required data from the messy data. Similar to the WHERE keyword in the SQL statement, certain
conditions are given, and the data that meets the conditions are filtered and merged. Show it.

1. filter() method

The filterO method is the filtering method provided by the Stream interface. This method can take a lambda expression as a parameter and then filter the elements in the stream according to the logic of the lambda expression. After filtering out the desired stream elements, you need to use the collectO method provided by Stream to re-encapsulate them according to the specified method.

Example 14.16

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class FilterOddDemo {
	 static void printeach(String message,List list) {			//输出集合元素
		System.out.print(message);								//输出文字信息
		list.stream().forEach(n->{								//使用forEach方法遍历集合并打印元素
			System.out.print(n+"");
		});
		System.out.println();									//换行
	}
 
 
 
public static void main(String[] args) {
	List<Integer> list = new ArrayList<>();						//创建空数组
	for(int i = 1; i<=10;i++) {									//从1循环到10
		list.add(i);											//给集合赋值
	}
	printeach("集合原有元素:",list);								//输出集合元素
	Stream<Integer> stream = list.stream();						//获取集合流对象
	//将集合中的所有奇数过滤出来,把过滤结果重新赋值给流对象
	stream = stream.filter(n->n%2==1);
	//将流对象重新封装成一个List集合
	List<Integer> result = stream.collect(Collectors.toList());
	printeach("过滤之后的集合元素:",result);							//输出集合元素
}
}

 The running results are as follows:

The three parts of "getting stream", "filtering stream" and "encapsulating stream" can be written in the same line of code. 

List<Integer> result = list.stream.().filter(n->%2==1).collect(Collectors.toList());

 Example 14.17

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class FilerDemo{	   //例题14.17
	public static void main(String[] args) {
		List<Employee> list=Employee.getEmpList();//获取公共类的测试数据
		Stream<Employee> stream = list.stream();//获取集合流对象
		//筛选年龄>30岁的员工
		stream=stream.filter(sx-> sx.getAge()>30);//将年龄大于30岁的员工过滤出来
		//限制条数
		stream = stream.limit(2);//将流对象重新封装成一个List集合
		List<Employee> result = stream.collect(Collectors.toList());//遍历结果集
		for (Employee sx : result) {//输出员工对象信息
			System.out.println(sx);
				
		}
	}
		 
}

The running results are as follows:

2. distinct() method 

This method can remove duplicate elements in the stream, and the effect is the same as the DISTINCT keyword in the SQL statement.

Example 14.18

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class DistinctDemo {  //例题14.18
	static void printeach(String message,List list) {	//输出集合元素
		System.out.print(message);						//输出文字信息
		list.stream().forEach(n->{						//使用fourEach方法遍历集合并打印元素
			System.out.println(n+"");
		});
		System.out.println();							//换行
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Integer>list=new ArrayList<Integer>();	//创建集合
		list.add(1);									//添加元素
		list.add(2);
		list.add(2);
		list.add(3);
		list.add(3);
		printeach("去重前:",list);						//打印集合元素
		Stream<Integer>stream=list.stream();			//获取集合流对象
		stream=stream.distinct();						//取出流中的重复元素
		List<Integer>reslut=stream.collect(Collectors.toList());//将流对象重新封装成一个List集合
		printeach("去重后:",result);
	}
 
}

 The running results are as follows:

3. Iimit() method

The Iimit() method is a method provided by the Stream interface. This method can obtain the first N elements in the stream.

Example 14.19

import java.util.List;
import java.util.stream.Collectors;
import java.util. stream.Stream;
	public class LimitDemo {		//例题14.19
		public static void main(String[] args){
			List<Employee> list = Employee.getEmpList();//获取公共类的测试数据
			Stream<Employee> stream = list.stream();//获取集合流对象
			stream = stream.filter(people ->"女".equals(people.getSex()));//将所有女员工过滤出来
			stream = stream.limit(2);//取出前两位
			List<Employee> result = stream.collect(Collectors.toList());//将流对象重新封装成一个List集合
			for (Employee emp : result) {//遍历结果集
				System.out.println(emp);//输出员工对象信息
			}
		}
	}
				

The running results are as follows:

4. skip method 

The skip() method is a method provided by the Stream interface. This method can ignore the first N elements in the stream.

Example 14.20

import java.util.List;
import java.util.stream.Collectors;
import java.util. stream.Stream;
public class SkipDemo {   //例题14.14
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			List<Employee> list = Employee.getEmpList();//获取公共类的测试数据
			Stream<Employee> stream = list.stream();//获取集合流对象
			stream = stream.filter(people ->"男".equals(people.getSex()));//将所有男员工过滤出来
			stream = stream.skip(2);//取出前两位
			List<Employee> result = stream.collect(Collectors.toList());//将流对象重新封装成一个List集合
			for (Employee emp : result) {//遍历结果集
				System.out.println(emp);//输出员工对象信息
			}
		}
	}
						

14.3.5 Data Mapping 

The concepts of data mapping and filtering are different: filtering is to find elements that meet the conditions in the stream, and mapping is to obtain specific data in the stream. The Stream interface provides the mapO method to implement data mapping. The mapO method will obtain a new stream object according to the function logic in the parameters. The element type in the new stream object may be different from the element type of the old stream object.

Example 14.21

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class MapDemo {
    public static void main(String[] args) {
        List<Employee> list = Employee.getEmpList();          // 获取公共类的测试数据
        Stream<Employee> stream = list.stream();              // 获取集合流对象
        // 将所有开发部的员工过滤出来
        stream = stream.filter(people -> "开发部".equals(people.getDept()));
        // 将所有员工的名字映射成一个新的流对象
        Stream<String> names = stream.map(Employee::getName);
        // 将流对象重新封装成一个List集合
        List<String> result = names.collect(Collectors.toList());
        for (String emp : result) {                              // 遍历结果集
            System.out.println(emp);                             // 输出所有姓名
        }
    }
}

The running results are as follows:

Example 14.22

import java.util.List;
import java.util.stream.DoubleStream;
import java.util.stream.Stream;
public class MapToInDemo {
    public static void main(String[] args) {
       List<Employee> list = Employee.getEmpList();      // 获取公共类的测试数据
       Stream<Employee> stream = list.stream();          // 获取集合流对象
       // 将所有开发部的员工过滤出来
       stream = stream.filter(people -> "销售部".equals(people.getDept()));
       // 将所有员工的名字映射成一个新的流对象
       DoubleStream salarys = stream.mapToDouble(Employee::getSalary);
       // 统计流中元素的数学总和
       double sum = salarys.sum();
       System.out.println("销售部一个月的薪资总额:"+sum);
    }
}

 The running results are as follows:

14.3.6 Data search

1.allMatch() method

This method will determine whether all elements in the stream meet a certain condition, and the return result is a boolean value.

Example 14.23

import java.util.List;
import java.util.stream.Stream;
 
public class AllMatchDemo {
    public static void main(String[] args) {
        List<Employee> list = Employee.getEmpList();       // 获取公共类的测试数据
        Stream<Employee> stream = list.stream();           // 获取集合流对象
        // 判断所有员工的年龄是否都大于25
        boolean result = stream.allMatch(people -> people.getAge() > 25);
        System.out.println("所有员工是否都大于25岁:" + result);  // 输出结果
    }
}

 The running results are as follows:

2.anyMatch method() method

This method will determine whether the elements in the stream meet a certain condition

Example 14.24

 
import java.util.List;
import java.util.stream.Stream;
public class AnyMatchDemo {
    public static void main(String[] args) {
        List<Employee> list = Employee.getEmpList();     // 获取公共类的测试数据
        Stream<Employee> stream = list.stream();         // 获取集合流对象
        // 判断员工是否有的年龄大于等于40
        boolean result = stream.anyMatch(people -> people.getAge() >= 40);
        System.out.println("员工中有年龄在40或以上的吗?:" + result); // 输出结果
 
    }
}

 The running results are as follows:

3.noneMatch() method

This method will determine whether all elements in the stream do not meet a certain condition

Example 14.25

import java.util.List;
import java.util.stream.Stream;
public class NoneMathchDemo {
    public static void main(String[] args) {
        List<Employee> list = Employee.getEmpList();        // 获取公共类的测试数据
        Stream<Employee> stream = list.stream();            // 获取集合流对象
        // 判断公司中是否不存在薪资小于2000的员工?
        boolean result = stream.noneMatch(people -> people.getSalary() <2000 );
        System.out.println("公司中是否不存在薪资小于2000元的员工?:" + result);// 输出结果
    }
}

The running results are as follows:

4.findFirst() method

This method will return the first element that meets the conditions

Example 14.26

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class FindFirstDemo {
    public static void main(String[] args) {
        // 获取公共类的测试数据
        List<Employee> list = Employee.getEmpList();
        Stream<Employee> stream = list.stream();             // 获取集合流对象
        // 过滤出21岁的员工
        stream = stream.filter(people -> people.getAge() == 21);
        Optional<Employee> young = stream.findFirst();      // 获取第一个元素
        Employee emp = young.get();                           // 获取员工对象
        System.out.println(emp);                              // 输出结果
    }
}

The running results are as follows:

The return value of this method is not a boolean value, but an Optional object

14.3.7 Data collection

1. Statistics

Not only can you filter out special elements, but you can also perform statistical calculations on the attributes of elements.

Example 14.27

 

 
import java.util.Comparator; // 比较器接口
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
 
public class ReducingDemo {
	public static void main(String[] args) {
		List<Employee> list = Employee.getEmpList(); // 获取测试数据
 
		long count = list.stream().count(); // 获取总人数
		// 下行代码也能实现获取总人数效果
		// count = stream.collect(Collectors.counting());
		System.out.println("公司总人数为:" + count);
 
		// 通过Comparator比较接口,比较员工年龄,再通过Collectors的maxBy()方法取出年龄最大的员工的Optional对象
		Optional<Employee> ageMax = list.stream().collect(Collectors.maxBy(Comparator.comparing(Employee::getAge)));
		Employee older = ageMax.get();// 获取员工对象
		System.out.println("公司年龄最大的员工是:\n    " + older);
 
		// 通过Comparator比较接口,比较员工年龄,再通过Collectors的minBy()方法取出年龄最小的员工的Optional对象
		Optional<Employee> ageMin = list.stream().collect(Collectors.minBy(Comparator.comparing(Employee::getAge)));
		Employee younger = ageMin.get();// 获取员工对象
		System.out.println("公司年龄最小的员工是:\n    " + younger);
 
		// 统计公司员工薪资总和
		double salarySum = list.stream().collect(Collectors.summingDouble(Employee::getSalary));
		System.out.println("公司的薪资总和为:" + salarySum); // 输出结果
 
		// 统计公司薪资平均数
		double salaryAvg = list.stream().collect(Collectors.averagingDouble(Employee::getSalary));
		// 使用格式化输出,保留2位小数
		System.out.printf("公司的平均薪资为:%.2f\n", salaryAvg);
 
		// 创建统计对象,利用summarizingDouble()方法获取员工薪资各方面的统计数据
		java.util.DoubleSummaryStatistics s = list.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
		System.out.print("统计:拿薪资的人数=" + s.getCount() + ", ");
		System.out.print("薪资总数=" + s.getSum() + ", ");
		System.out.print("平均薪资=" + s.getAverage() + ", ");
		System.out.print("最大薪资=" + s.getMax() + ", ");
		System.out.print("最小薪资=" + s.getMin() + "\n");
 
		// 将公司员工姓名拼成一个字符串,用逗号分隔
		String nameList = list.stream().map(Employee::getName).collect(Collectors.joining(", "));
		System.out.println("公司员工名单如下:\n    " + nameList);
	}
}

The running results are as follows:

2. Data grouping

Save elements in the stream separately according to specified conditions

Data grouping includes one-level grouping and multi-level grouping

First-level grouping: classify all data according to one condition

Example 14.28

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class GroupDemo1{
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List<Employee> list = Employee.getEmpList();
		Stream<Employee>stream=list.stream();
		Map<String,List <Employee>> map = stream.collect(Collectors.groupingBy(Employee::getDept));
		Set<String>depts=map.keySet();
		for(String dept:depts) {
			System.out.println(dept+"员工信息如下:");
			List<Employee>temp=map.get(dept);
			for(Employee e:temp) {
				System.out.println(e);
			}
			System.out.println();
		}
	}
 
}

 The running results are as follows:

difficulty:

The grouping rule is a function, which is called by the Collectors collector class, not the Stream stream object.
Map<K,List<T>> has two generics. The first generic is the type of the group, and the second is the type of the collection of elements in the group. In the example, the groups are grouped according to the department name, so the type of K is the String type; the elements within the department are employee collections, so the type of the List collection generic T should be the Employee type

Example 14.29

 
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
public class GroupingDemo2 {
	public static void main(String[] args) {
		List<Employee> list = Employee.getEmpList(); // 获取公共类的测试数据
		Stream<Employee> stream = list.stream(); // 获取集合流对象
		// 一级分组规则方法,按照员工部门进行分级
		Function<Employee, String> deptFunc = Employee::getDept;
		// 二级分组规则方法,按照员工部门进行分级
		Function<Employee, String> sexFunc = Employee::getSex;
		// 将流中的数据进行二级分组,先对员工部分进行分组,在对员工性别进行分组
		Map<String, Map<String, List<Employee>>> map = stream
				.collect(Collectors.groupingBy(deptFunc, Collectors.groupingBy(sexFunc)));
		// 获取Map的中的一级分组键集合,也就是部门名称集合
		Set<String> deptSet = map.keySet();
		for (String deptName : deptSet) { // 遍历部门名称集合
			// 输出部门名称
			System.out.println("【" + deptName + "】 部门的员工列表如下:");
			// 获取部门对应的二级分组的Map对象
			Map<String, List<Employee>> sexMap = map.get(deptName);
			// 获得二级分组的键集合,也就是性别集合
			Set<String> sexSet = sexMap.keySet();
			for (String sexName : sexSet) { // 遍历部门性别集合
				// 获取性别对应的员工集合
				List<Employee> emplist = sexMap.get(sexName);
				System.out.println("    【" + sexName + "】 员工:"); // 输出性别种类
				for (Employee emp : emplist) {// 遍历员工集合
					System.out.println("        " + emp); // 输出对应员工信息
				}
			}
		}
	}
}

The running results are as follows:

difficulty:

The parameters of the two groupingBy0 methods in the example are different, one is groupingBy (gender grouping rule), the other is groupingBy (department grouping rule, groupingBy (gender grouping rule)).
The obtained Map object also contains a nested Map object. Its structure is as follows: Map<Department, Map<Gender, List<Employee>>>
Counting from the left, the first Map object is grouped at the first level, and the second Map object is grouped at the second level.

 

Guess you like

Origin blog.csdn.net/2301_76549195/article/details/133907639