Java8新特性

  • 速度更快(例如在HashMap底层使用:数组-链表-红黑树 、ConcurrentHashMap底层使用:数组-链表-红黑树 CAS+ synchronized)
  • 代码更少(增加了新的语法Lambda表达式)
  • 强大的Stream API
  • 便于并行
  • 最大化减少空指针异常 Optional

Lambda表达式

为什么使用Lambda表达式

Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

对比匿名内部类

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {

	//原来的匿名内部类
	@Test
	public void test1() {
		Comparator<Integer> com = new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				
				return Integer.compare(o1, o2);
			}
		};
		
		TreeSet<Integer> ts = new TreeSet<>(com);
	}
	
	//Lambda 表达式
	@Test
	public void test2() {
		Comparator<Integer> com = (x,y) -> Integer.compare(x, y);
		TreeSet<Integer> ts = new TreeSet<>(com);
	}
}

需求一:获取当前公司中员工年龄大于35的员工信息

创建Employee类

package com.java8;

public class Employee {
	private String name;
	private int age;
	private double salary;
	public Employee() {
	}
	public Employee(String name, int age, double salary) {
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + "]";
	}
}

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	//需求一:获取当前公司中员工年龄大于35的员工信息
	public List<Employee> filterEmployees(List<Employee> list){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(emp.getAge() > 35) {
				emps.add(emp);
			}
		}
		return emps;
		
	}
	@Test
	public void test3() {
		List<Employee> list = filterEmployees(employees);
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
}

在这里插入图片描述

需求二:获取当前公司中员工年龄大于35的员工信息

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);

	//需求二:获取当前公司中员工工资大于5000的员工信息          
	//~我们发现代码大量重复~
	public List<Employee> filterEmployees2(List<Employee> list){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(emp.getSalary() > 5000) {
				emps.add(emp);
			}
		}
		return emps;
	}
	@Test
	public void test4() {
		List<Employee> list = filterEmployees2(employees);
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
}

在这里插入图片描述

优化方法一:策略设计模式

实现需求一

创建MyPredicate 接口

package com.java8;

public interface MyPredicate<T> {

	public boolean test(T t);
	
}

创建FilterEmployeeByAge 实现MyPredicate

package com.java8;

public class FilterEmployeeByAge implements MyPredicate<Employee> {

	@Override
	public boolean test(Employee t) {
		return t.getAge() > 35;
	}

}
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	//优化方式一:
	public List<Employee> filterEmployee(List<Employee> list,MyPredicate<Employee> mp){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(mp.test(emp)) {
				emps.add(emp);
			}
		}
		return emps;
	}
	@Test
	public void test5() {
		List<Employee> list = filterEmployee(employees , new FilterEmployeeByAge());
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
}

在这里插入图片描述

实现需求二

创建FilterEmployeeBySalary 实现MyPredicate接口

package com.java8;

public class FilterEmployeeBySalary implements MyPredicate<Employee> {

	@Override
	public boolean test(Employee t) {
		return t.getSalary() > 5000;
	}

}
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);

	
	//优化方式一:
	public List<Employee> filterEmployee(List<Employee> list,MyPredicate<Employee> mp){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(mp.test(emp)) {
				emps.add(emp);
			}
		}
		return emps;
	}
	@Test
	public void test5() {
		List<Employee> list = filterEmployee(employees , new FilterEmployeeByAge());
		for (Employee employee : list) {
			System.out.println(employee);
		}
		
		System.out.println("-----------------------------------");
		
		List<Employee> list2 = filterEmployee(employees , new FilterEmployeeBySalary());
		for (Employee employee : list2) {
			System.out.println(employee);
		}
	}
}

但是每次都需要创建类,麻烦

优化方式二:匿名内部类

直接不需要写实现类

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	public List<Employee> filterEmployee(List<Employee> list,MyPredicate<Employee> mp){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(mp.test(emp)) {
				emps.add(emp);
			}
		}
		return emps;
	}

	
	//优化方式二:匿名内部类
	@Test
	public void test6() {
		List<Employee> list = filterEmployee(employees, new MyPredicate<Employee>() {
			@Override
			public boolean test(Employee t) {
				return t.getSalary() < 5000;
			}
		});
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}
}

在这里插入图片描述

优化方式三:Lambda表达式

更加简化

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	public List<Employee> filterEmployee(List<Employee> list,MyPredicate<Employee> mp){
		List<Employee> emps = new ArrayList<Employee>();
		for (Employee emp : list) {
			if(mp.test(emp)) {
				emps.add(emp);
			}
		}
		return emps;
	}

	
	//优化方式三:Lambda 表达式
	@Test
	public void test7() {
		List<Employee> list = filterEmployee(employees, (e) -> e.getSalary() <= 5000);
		list.forEach(System.out::println);
	}
}

在这里插入图片描述

优化方式四:StreamAPI

更更简洁
没有接口,也没有方法

```java
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;

import org.junit.Test;

public class TestLambda {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	//优化方式四
	public void test8() {
		employees.stream()
				 .filter((e) -> e.getSalary() > 5000)
				 .forEach(System.out::println);
		
		//只取前n个  这取第一个
		System.out.println("---------------取第一个------------------");
		employees.stream()
		 .filter((e) -> e.getSalary() < 5000)
		 .limit(1)
		 .forEach(System.out::println);
		
		//把集合中所有名字提取出来
		System.out.println("---------------把集合中所有名字提取出来------------------");
		employees.stream()
				 .map(Employee::getName)
				 .forEach(System.out::println);
		
		
	}
}

Lambda基础语句

Lambda 表达式的基础语法:Java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或Lambda 操作符。
箭头操作符将Lambda表达式拆分成两部分

  • 左侧:Lambda 表达式的参数列表
  • 右侧:Lambda 表达式中所需执行的功能(Lambda体)

语法格式一:无参数,无返回值

()-> System.out.println(“Hello Lambda!”)

package com.java8;

import org.junit.Test;

/**
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->"  该操作符称为箭头操作符或Lambda 操作符
 * 							箭头操作符将Lambda表达式拆分成两部分
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能(Lambda体)
 * 
 * 语法格式一:无参数,无返回值
 * 		()-> System.out.println("Hello Lambda!")
 * 		
 *
 */
public class TestLambda2 {
	@Test
	public void test1() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello Lambda!");
			}
		};
		r.run();
		System.out.println("------------------------------");
		Runnable r1 = () -> System.out.println("Hello Lambda!");
		r1.run();
	}
}

在这里插入图片描述

语法格式二:有一个参数,并且无返回值

(x) -> System.out.println(x);

package com.java8;

import java.util.function.Consumer;

import org.junit.Test;

/**
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->"  该操作符称为箭头操作符或Lambda 操作符
 * 							箭头操作符将Lambda表达式拆分成两部分
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能(Lambda体)
 * 
 * 语法格式一:无参数,无返回值
 * 		()-> System.out.println("Hello Lambda!")
 * 
 * 语法格式二:有一个参数,并且无返回值
 * 	    (x) -> System.out.println(x);
 *
 */
public class TestLambda2 {
	@Test
	public void test2() {
		Consumer<String> c = (x) -> System.out.println(x);
		c.accept("语法格式二:有一个参数,并且无返回值");
	}
}

语法格式三:若只有一个参数,小括号可以不写

x -> System.out.println(x);

package com.java8;

import java.util.function.Consumer;

import org.junit.Test;

/**
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->"  该操作符称为箭头操作符或Lambda 操作符
 * 							箭头操作符将Lambda表达式拆分成两部分
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能(Lambda体)
 * 
 * 语法格式一:无参数,无返回值
 * 		()-> System.out.println("Hello Lambda!")
 * 
 * 语法格式二:有一个参数,并且无返回值
 * 	    (x) -> System.out.println(x);
 * 语法格式三:若只有一个参数,小括号可以不写
 * 		x -> System.out.println(x);
 */
public class TestLambda2 {
	@Test
	public void test2() {
		Consumer<String> c = x -> System.out.println(x);
		c.accept("语法格式二:有一个参数,并且无返回值");
	}
}

语法格式四:有两个以上参数,有返回值,并且Lambda 体中有多条语句

(x,y) -> { }

package com.java8;

import java.util.Comparator;
import java.util.function.Consumer;

import org.junit.Test;

/**
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->"  该操作符称为箭头操作符或Lambda 操作符
 * 							箭头操作符将Lambda表达式拆分成两部分
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能(Lambda体)
 * 
 * 语法格式一:无参数,无返回值
 * 		()-> System.out.println("Hello Lambda!")
 * 语法格式二:有一个参数,并且无返回值
 * 	    (x) -> System.out.println(x);
 * 语法格式三:若只有一个参数,小括号可以不写
 * 		x -> System.out.println(x);
 * 语法格式四:有两个以上参数,有返回值,并且Lambda 体中有多条语句
 * 		(x,y) -> {         }
 *	
 *
 * 
 */
public class TestLambda2 {
	@Test
	public void test3() {
		Comparator<Integer> com = (x,y) -> {
			System.out.println("语法格式四:有两个以上参数,有返回值,并且Lambda 体中有多条语句");
			return Integer.compare(x, y);
		};
	}
}

语法格式六:若Lambda 体中只有一条语句,return 和大括号都可以省略不写

(x,y) -> Integer.compare(x, y);

package com.java8;

import java.util.Comparator;
import java.util.function.Consumer;

import org.junit.Test;

/**
 * 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->"  该操作符称为箭头操作符或Lambda 操作符
 * 							箭头操作符将Lambda表达式拆分成两部分
 * 
 * 左侧:Lambda 表达式的参数列表
 * 右侧:Lambda 表达式中所需执行的功能(Lambda体)
 * 
 * 语法格式一:无参数,无返回值
 * 		()-> System.out.println("Hello Lambda!")
 * 语法格式二:有一个参数,并且无返回值
 * 	    (x) -> System.out.println(x);
 * 语法格式三:若只有一个参数,小括号可以不写
 * 		x -> System.out.println(x);
 * 语法格式四:有两个以上参数,有返回值,并且Lambda 体中有多条语句
 * 		(x,y) -> {         }
 * 语法格式五:有两个以上参数,有返回值,并且Lambda 体中有多条语句
 * 		(x,y) -> {         }
 * 语法格式六:若Lambda 体中只有一条语句,return 和大括号都可以省略不写
 * 		(x,y) -> Integer.compare(x, y);
 */
public class TestLambda2 {
	@Test
	public void test4() {
		Comparator<Integer> com = (x,y) -> Integer.compare(x, y);
	}
}

语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即"类型推断"

(Integer x,Integer y) -> Integer.compare(x, y);

	@Test
	public void test5() {
		Comparator<Integer> com = (Integer x,Integer y) -> Integer.compare(x, y);
	}

左右遇一括号省
左侧推断类型省

Lambda 表达式需要“函数式接口”的支持

什么是函数式接口

接口只有一个抽象方法的接口,称为函数式接口。
可以使用使用注解@FunctionalInterface修饰,
修饰之后,可以检查该接口是否是函数式接口。

  • 例如:
    在这里插入图片描述
    里面只能有一个抽象方法。
    在这里插入图片描述

Lambda练习

  1. 调用Collections.sort()方法,通过定制排序比较两个Employee(先按年龄比,年龄相同按姓名比,使用Lambda作为参数传递)。
package com.java8;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class TestLambda3 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);

	@Test
	public void test1() {
		//定制排序
		Collections.sort(employees,(e1,e2) -> {
			if(e1.getAge() == e2.getAge()) {
				return e1.getName().compareTo(e2.getName());
			}else {
				return Integer.compare(e1.getAge(), e2.getAge());
			}
		});
		for (Employee employee : employees) {
			System.out.println(employee);
		}
	}
}

在这里插入图片描述

  1. ①声明函数式接口,接口中声明抽象方法,public String getValue(String str);
    ②声明类TestLambda,类中编写方法使用接口作为参数,将一个字符串转换成大写,并作为方法的返回值。
    ③再将一个字符串的索引位置进行2和5截取子串。
package com.java8;

@FunctionalInterface
public interface MyFunction {

	public String getValue(String str);

}
package com.java8;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class TestLambda3 {
	//需求:用于处理字符串
	public String strHandler(String str,MyFunction mf) {
		return mf.getValue(str);
	}
	
	@Test
	public void test2() {
		String toUpperCase = strHandler("abcdefg",(str) -> str.toUpperCase());
		System.out.println(toUpperCase);
		String substring = strHandler(toUpperCase,(str) -> str.substring(2,5));
		System.out.println(substring);
	}
}

在这里插入图片描述
3. ①声明一个带两个泛型的函数式接口,泛型类型为<T,R> T为参数,R为返回值。
②接口中声明对应抽象方法。
③在TestLambda类中声明方法,使用接口作为参数,计算两个long型参数的和。
④再计算两个long型参数的乘积。

package com.java8;

@FunctionalInterface
public interface MyFunction2<T,R> {
	
	public R getValue(T t1,T t2);
	
}
package com.java8;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.junit.Test;

public class TestLambda3 {

	//需求:对于两个Long型数据进行处理
	public void op(Long l1,Long l2,MyFunction2<Long,Long> mf) {
		System.out.println(mf.getValue(l1, l2));
	}
	
	@Test
	public void test3() {
		op(100L, 200L, (x,y) -> x*y);
	}
}

四大内置核心函数式接口

在这里插入图片描述

  • Consumer : 消费型接口

void accept(T t);

  • Supplier : 供给型接口

T get();

  • Function<T,R> : 函数型接口

R aaply(T t);

  • Predicate : 断言型接口

boolean test(T t)

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.junit.Test;

/**
 * Java8 内置的四大核心函数式接口
 *
 * Consumer<T> : 消费型接口
 * 		void accept(T t);
 * 
 * Supplier<T> : 供给型接口
 * 		T get();
 * 
 * Function<T,R> : 函数型接口
 * 		R aaply(T t);
 * 
 * Predicate<T> : 断言型接口
 * 		boolean test(T t)
 */
public class TestLambda4 {
	
	//Consumer<T> : 消费型接口
	@Test
	public void test1() {
		happy(10000, (x) -> System.out.println("消费了"+x+"元"));
	}
	public void happy(double money,Consumer<Double> con) {
		con.accept(money);
	}
	
	//Supplier<T> : 供给型接口
	@Test
	public void test2() {
		List<Integer> numList = getNumList(10, () -> (int)(Math.random()*100));
		for (Integer num : numList) {
			System.out.println(num);
		}
		
	}
	//产生一些整数,并放入集合
	public List<Integer> getNumList(int num,Supplier<Integer> sup){
		List<Integer> list = new ArrayList<>();
		for (int i = 0; i < num; i++) {
			Integer n = sup.get();
			list.add(n);
		}
		return list;
	}
	
	//Function<T,R> : 函数型接口
	@Test
	public void test3() {
		String newStr = strHander("\t\t\t 武汉加油!\t", (x) -> x.trim());
		System.out.println(newStr);
		String newStr1 = strHander("武汉加油!", (x) -> x.substring(2, 4));
		System.out.println(newStr1);
	}
	//需求用于处理字符串
	public String strHander(String str,Function<String,String> fun) {
		return fun.apply(str);
	}
	
	//Predicate<T> : 断言型接口
	@Test
	public void test4() {
		List<String> list = Arrays.asList("Hello","ok","www","wuhan","jiayou");
		List<String> filterStr = filterStr(list, (s) -> s.length()>3);
		for (String str : filterStr) {
			System.out.println(str);
		}
	}
	//需求将满足条件的字符串,放入集合中去
	public List<String> filterStr(List<String> list,Predicate<String> pre){
		List<String> strlist = new ArrayList<>();
		for (String str : strlist) {
			if(pre.test(str)) {
				strlist.add(str);
			}
		}
		return strlist;
	}
}

其他接口

在这里插入图片描述

方法引用与构造器引用

方法引用

方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用"方法引用"。
(可以理解为:方法引用是Lambda表达式的另一种表现形式)

主要由三种语法形式:

  1. 对象::实例方法名
  2. 类::静态方法名
  3. 类::实例方法名

注意:

  1. Lambda体中调用方法的参数列表和返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
  2. 若需要使用(类::实例方法名),则要求Lambda参数列表中的第一参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method 。

对象::实例方法名

package com.java8;

import java.io.PrintStream;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.junit.Test;

/**
 * 方法引用:若Lambda体中的内容有方法已经实现了,我们可以使用"方法引用"
 *			(可以理解为:方法引用是Lambda表达式的另一种表现形式)
 * 主要由三种语法形式:
 * 1.	对象::实例方法名
 * 2.   类::静态方法名
 * 3.   类::实例方法名
 * 
 * 注意:参数和返回值要一致
 */
public class TestMethodRef {

	//对象::实例方法名
	@Test
	public void test1() {
		PrintStream ps = System.out;
		Consumer<String> con = (x) -> ps.println(x);
		
		PrintStream ps1 = System.out;
		Consumer<String> con1 = ps1::println;
		con1.accept("对象::实例方法名");
		
	}
	//对象::实例方法名
	@Test
	public void test2() {
		Employee employee = new Employee();
		employee.setName("张三");
		employee.setAge(18);
		Supplier<String> sup = () -> employee.getName();
		System.out.println(sup.get());
		System.out.println("----------------------");
		Supplier<Integer> sup1 = employee::getAge;
		System.out.println(sup1.get());
		
	}
}

在这里插入图片描述
在这里插入图片描述

类::静态方法名

public class TestMethodRef {
	
	//类::静态方法名
	@Test
	public void test1() {
		Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
		
		Comparator<Integer> com1 = Integer::compare;
	}
}

类::实例方法名

public class TestMethodRef {
	
	//类::实例方法名
	@Test
	public void test1() {
		BiPredicate<String,String> bp = (x,y) -> x.equals(y);
		
		BiPredicate<String,String> bp1 = String::equals;
	}
}

构造器引用

格式:
ClassName::new

注意:
需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。

无参数构造器:

	//构造器引用
	@Test
	public void test1() {
		Supplier<Employee> sup = () -> new Employee();
		
		Supplier<Employee> sup1 = Employee::new;
	}

有参数构造器:
在这里插入图片描述

	@Test
	public void test2() {
		Function<Integer,Employee> fun = (x) -> new Employee(x);
		
		Function<Integer,Employee> fun1 = Employee::new;
		Employee emp = fun1.apply(101);
		System.out.println(emp);
	}

在这里插入图片描述

数组引用

type::new

	//数组引用
	@Test
	public void test3() {
		Function<Integer,String[]> fun = (x) -> new String[x];
		String[] str = fun.apply(10);
		System.out.println(str.length);
		
		Function<Integer,String[]> fun1 = String[]::new;
		String[] str1 = fun.apply(20);
		System.out.println(str1.length);
	}

在这里插入图片描述

Stream API

了解Stream

Java8中有两大最为重要的改变。第一个是Lambda表达式:另外一个则是Stream API(java.util.stream.*)。
Stream是java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API对集合数据进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简而言之,Stream API提供了一种高效且易于使用的处理数据的方式。
在这里插入图片描述

什么是Stream?

流(Stream)到底是什么?

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
"集合讲的是数据,流讲的是计算!"
注意:

  • Stream自己不会存储元素。
  • Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream操作是延迟执行的。

Stream的操作三个步骤

1.创建Stream

一个数据源(如:集合、数组),获取一个流

2.中间操作

一个中间操作链,对数据源的数据进行处理

3.终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果
在这里插入图片描述

1.创建Stream演示

  1. 可以通过Collection系列集合提供的stream() 或 parallelStream()
  2. 通过Arrays中的静态方法stream()获取数组流
  3. 通过Stream中的静态方法of()
  4. 创建无限流 :① 使用迭代的方式 ;② 使用生成的方式
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI1 {
	//创建Stream
	@Test
	public void test1() {
		//1. 可以通过Collection系列集合提供的stream() 或  parallelStream()
		List<String> list = new ArrayList<>();
		Stream<String> stream1 = list.stream();
		
		//2. 通过Arrays中的静态方法stream()获取数组流
		Employee[] emps = new Employee[10];
		Stream<Employee> stream2 = Arrays.stream(emps);
		
		//3.通过Stream中的静态方法of()
		Stream<String> stream3 = Stream.of("aa","bb","cc");
		
		//4.创建无限流
		//① 使用迭代的方式
		Stream<Integer> stream4 = Stream.iterate(0, (x) -> x+2);
		//加上中间操作和终止操作演示一下
		stream4.limit(10).forEach(System.out::println); //打印前十个
		
		System.out.println("-------------------------");
		//② 使用生成的方式
		Stream.generate(() -> Math.random())
			  .limit(5)
			  .forEach(System.out::println);
	}
}

在这里插入图片描述

2.中间操作演示

筛选与切片

在这里插入图片描述

filter
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	//中间操作
	/*
	 * 筛选与切片 
	 * filter-接收Lambda,从流中排除某些元素。 limit-截断流,使其元素不超过给定数量。
	 * skip(n)-跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
	 * distinct-筛选,通过流所生成元素的hashCode() 和 equals()去除重复元素
	 */
	@Test
	public void test1() {
		//中间操作
		Stream<Employee> stream = employees.stream()
				                           .filter((e) -> {
				                        	   System.out.println("Stream API 的中间操作");
				                        	   return e.getAge() > 35;
				                           });

	}
}

无打印信息
在这里插入图片描述
加上终止操作

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	//中间操作
	/*
	 * 筛选与切片 
	 * filter-接收Lambda,从流中排除某些元素。 limit-截断流,使其元素不超过给定数量。
	 * skip(n)-跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
	 * distinct-筛选,通过流所生成元素的hashCode() 和 equals()去除重复元素
	 */
	@Test
	public void test1() {
		//中间操作
		Stream<Employee> stream = employees.stream()
				                           .filter((e) -> {
				                        	   System.out.println("Stream API 的中间操作");
				                        	   return e.getAge() > 35;
				                           });
		//终止操作
		stream.forEach(System.out::println);
				 
	}
}

在这里插入图片描述
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

limit
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	//中间操作
	/*
	 * 筛选与切片 
	 * filter-接收Lambda,从流中排除某些元素。 limit-截断流,使其元素不超过给定数量。
	 * skip(n)-跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
	 * distinct-筛选,通过流所生成元素的hashCode() 和 equals()去除重复元素
	 */
	@Test
	public void test1() {
		//中间操作
		Stream<Employee> stream = employees.stream()
				                           .filter((e) -> e.getSalary()> 5000);
		//终止操作
		stream.forEach(System.out::println); 
	}
}

在这里插入图片描述

package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	//中间操作
	/*
	 * 筛选与切片 
	 * filter-接收Lambda,从流中排除某些元素。 limit-截断流,使其元素不超过给定数量。
	 * skip(n)-跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
	 * distinct-筛选,通过流所生成元素的hashCode() 和 equals()去除重复元素
	 */
	@Test
	public void test1() {
		//中间操作
		Stream<Employee> stream = employees.stream()
				                           .filter((e) -> e.getSalary()> 5000)
				                           .limit(2);
		//终止操作
		stream.forEach(System.out::println);
				 
	}
}

在这里插入图片描述

映射
map
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	

	@Test
	public void test1() {
		List<String> list = Arrays.asList("aa","bb","cc","dd","ee");
		
		list.stream()
			.map((str) -> str.toUpperCase())
			.forEach(System.out::println);

		System.out.println("-----------------------------------");
		
		employees.stream()
				 .map(Employee::getName)
				 .forEach(System.out::println);
		
		System.out.println("-----------------------------------");
		
		Stream<Stream<Character>> stream = list.stream()
			.map(TestStreamAPI2::filterCharacter);
		
		stream.forEach((sm) ->{
			sm.forEach(System.out::println);
		});	
	}
	
	public static Stream<Character> filterCharacter(String str){
		List<Character> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch);
		}
		
		return list.stream();
	}
}

在这里插入图片描述

flatMap
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	

	@Test
	public void test1() {
		List<String> list = Arrays.asList("aa","bb","cc","dd","ee");
		
		
		Stream<Character> stream = list.stream()
			.flatMap(TestStreamAPI2::filterCharacter);
		
		stream.forEach(System.out::println);
		
		
	}
	
	public static Stream<Character> filterCharacter(String str){
		List<Character> list = new ArrayList<>();
		
		for (Character ch : str.toCharArray()) {
			list.add(ch);
		}
		return list.stream();
	}
}

在这里插入图片描述

排序
排序
 	sorted()——自然排序(Comparable)
 	sorted(Comparator com)——定制排序(Comparator)
sorted()——自然排序
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",48,22999.99),
			new Employee("田七",8,73129.99)
	);
	
	/*
	 	排序
	 	sorted()——自然排序(Comparable)
	 	sorted(Comparator com)——定制排序(Comparator)
	 */
	@Test
	public void test1() {
		List<String> list = Arrays.asList("dd","bb","ee","cc","aa");
		list.stream()
			.sorted()
			.forEach(System.out::println);
		
	}
}

在这里插入图片描述

sorted(Comparator com)——定制排序
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI2 {
	
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99),
			new Employee("李四",28,2229.99),
			new Employee("王五",38,9449.99),
			new Employee("赵六",38,22999.99),
			new Employee("田七",8,73129.99),
			new Employee("狗八",38,22999.99)
	);
	
	/*
	 	排序
	 	sorted()——自然排序(Comparable)
	 	sorted(Comparator com)——定制排序(Comparator)
	 */
	@Test
	public void test1() {
		List<String> list = Arrays.asList("dd","bb","ee","cc","aa");
		list.stream()
			.sorted()
			.forEach(System.out::println);
		
		System.out.println("--------------------------");
		employees.stream()
				 .sorted((e1,e2) -> {
					 if(e1.getAge().equals(e2.getAge())) {
						 return e1.getName().compareTo(e2.getName());
					 }else {
						 return e1.getAge().compareTo(e2.getAge());
					 }
				 }).forEach(System.out::println);
		
	}
}

在这里插入图片描述

3.终止操作演示

查找与匹配
  • allMathch——检查是否匹配所有元素
  • anyMatch——检查是否至少匹配一个元素
  • noneMatch——检查是否没有匹配所有元素
  • findFirst——返回第一个元素
  • findAny——返回当前流中的任意元素
  • count——返回流中元素的总个数
  • max——返回流中最大值
  • min——返回流中最小值
package com.java8;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.Test;

import com.java8.Employee.Status;

/*
 * Stream的操作三个步骤:
 * 
 * 1.创建Stream
 *
 * 2.中间操作
 *
 * 3.终止操作(终端操作)
*/
public class TestStreamAPI3 {
	List<Employee> employees = Arrays.asList(
			new Employee("张三",18,4999.99,Status.FREE),
			new Employee("李四",28,2229.99,Status.BUSY),
			new Employee("王五",38,9449.99,Status.VOCATION),
			new Employee("赵六",38,22999.99,Status.FREE),
			new Employee("田七",8,73129.99,Status.BUSY)
	);
	
	//终止操作
	
	/**
	 * 查找与匹配
 		- allMathch——检查是否匹配所有元素
		- anyMatch——检查是否至少匹配一个元素
		- noneMatch——检查是否没有匹配所有元素
		- findFirst——返回第一个元素
		- findAny——返回当前流中的任意元素
		- count——返回流中元素的总个数
		- max——返回流中最大值
		- min——返回流中最小值
	 */
	@Test
	public void test1() {
		//是否所有元素都是BUSY
		boolean b1 = employees.stream()
				 .allMatch((e) -> e.getStatus().equals(Status.BUSY));
		System.out.println("allMatch:"+b1);

		//是否至少有一个元素是BUSY
		boolean b2 = employees.stream()
				 .anyMatch((e) -> e.getStatus().equals(Status.BUSY));
		System.out.println("anyMatch:"+b2);
		
		//是否当中没有BUSY
		boolean b3 = employees.stream()
			     .noneMatch((e) -> e.getStatus().equals(Status.BUSY));
		System.out.println("noneMatch:"+b3);
		
		//返回工资从低到高的第一个元素
		Optional<Employee> op = employees.stream()
				.sorted((e1,e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
				.findFirst();
		//注意当返回值有可能为空,就会封装到Optional中
		System.out.println("findFirst:"+op);
		
		//返回状态为FREE任意一个元素    parallelStream()是获取并行流
		Optional<Employee> op1 = employees.parallelStream()
				.filter((e) -> e.getStatus().equals(Status.FREE))
				.findAny();
		System.out.println("findAny:"+op1.get());
		
		//返回流中元素数量
		long count = employees.stream().count();
		System.out.println("count:"+count);
		
		//返回流中最大值 工资最大的对象
		Optional<Employee> max = employees.stream()
				 .max((e1,e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		System.out.println("max"+max.get());
		
		//返回流中最小值 工资的最小值
		Optional<Double> min = employees.stream()
				 .map(Employee::getSalary)
				 .min(Double::compare);
		System.out.println("min:"+min);
		
	}

}

在这里插入图片描述

归约与收集

接口中的默认方法与静态方法

新时间日期API

其他新特性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值