【Way to java】Java8 新特性 1

Java8简介

  • 速度更快
  • 代码更少(新增了新的语法Lambda表达式)
  • 强大的Stream API
  • 便于并行
  • 最大化减少空指针异常Optional

其中最为核心的是Lambda表达式Stream API

Lambda表达式

简介

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

案例

场景:从员工集合中筛选某些条件的员工

List<Employee> emps = Arrays.asList(
		new Employee(101, "张三", 18, 9999.99),
		new Employee(102, "李四", 59, 6666.66),
		new Employee(103, "王五", 28, 3333.33),
		new Employee(104, "赵六", 8, 7777.77),
		new Employee(105, "田七", 38, 5555.55)
);

方案一:for循环筛选

//需求:获取公司中年龄小于 35 的员工信息
public List<Employee> filterEmployeeAge(List<Employee> emps){
	List<Employee> list = new ArrayList<>();
	for (Employee emp : emps) {
		if(emp.getAge() <= 35){
			list.add(emp);
		}
	}
	return list;
}

方案二:通过策略设计模式泛型调用,后续增加规则类

@FunctionalInterface
public interface MyPredicate<T> {
	public boolean test(T t);
}

public class FilterEmployeeForAge implements MyPredicate<Employee>{
	@Override
	public boolean test(Employee t) {
		return t.getAge() <= 35;
	}
}
public List<Employee> filterEmployee(List<Employee> emps, MyPredicate<Employee> mp){
	List<Employee> list = new ArrayList<>();
	for (Employee employee : emps) {
		if(mp.test(employee)){
			list.add(employee);
		}
	}
	return list;
}

方案三:通过匿名内部类

@Test
public void test5(){
	List<Employee> list = filterEmployee(emps, new MyPredicate<Employee>() {
		@Override
		public boolean test(Employee t) {
			return t.getId() <= 103;
		}
	});
	for (Employee employee : list) {
		System.out.println(employee);
	}
}

方案四:通过lambda表达式

@Test
public void test6(){
	List<Employee> list = filterEmployee(emps, (e) -> e.getAge() <= 35);
	list.forEach(System.out::println);
	
	System.out.println("------------------------------------------");
	
	List<Employee> list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
	list2.forEach(System.out::println);
}

方案五:Stream API

@Test
public void test7(){
	emps.stream()
		.filter((e) -> e.getAge() <= 35)
		.forEach(System.out::println);
	System.out.println("---------------------------------");
	emps.stream()
		.map(Employee::getName)
		.limit(3)
		.sorted()
		.forEach(System.out::println);
}

语法

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能

无参 无返回值

@Test
public void test1(){
	int num = 0;//jdk1.7前,必须是final,1.8后可以不用写但是不能num++
	Runnable r = new Runnable() {
		@Override
		public void run() {
			System.out.println("Hello World!" + num);
		}
	};
	r.run();
	System.out.println("-------------------------------");
	Runnable r1 = () -> System.out.println("Hello Lambda!");
	r1.run();
}

一个参数 无返回值

@Test
public void test2(){
	Consumer<String> con = x -> System.out.println(x);
	con.accept("Hello world!");
}

两个以上的参数,有返回值,有多条语句

Comparator<Integer> com = (x, y) -> {
	System.out.println("函数式接口");
	return Integer.compare(x, y);
};

两个以上的参数,有返回值,一条语句

// return和大括号可以省略
// 
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

总结

  1. Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断” ,也可以声明参数类型例如 (Integer x, Integer y) -> Integer.compare(x, y);
  2. 接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰可以检查是否是函数式接口

函数式接口

简介

  1. 只包含一个抽象方法的接口,称为函数式接口。
  2. 可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda
    表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方
    法上进行声明)
  3. 我们可以在任意函数式接口上使用 @FunctionalInterface 注解,
    这样做可以检查它是否是一个函数式接口,同时 javadoc 也会包
    含一条声明,说明这个接口是一个函数式接口

四大内置核心函数式接口

消费型接口

Consumer<T> void accept(T t);

@Test
public void test1(){
	happy(100, (m) -> System.out.println("此次消费" + m + "元"));
} 
public void happy(double money, Consumer<Double> con){
	con.accept(money);
}

供给型接口

Supplier<T> T get();

@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> R apply(T t);

@Test
public void test3(){
	String newStr = strHandler("\t\t\t Helloworld   ", (str) -> str.trim());
	System.out.println(newStr);
	String subStr = strHandler("我大尚硅谷威武", (str) -> str.substring(2, 5));
	System.out.println(subStr);
}
//需求:用于处理字符串
public String strHandler(String str, Function<String, String> fun){
	return fun.apply(str);
}

断言型接口

Predicate<T> boolean test(T t);

@Test 
public void test4(){
	List<String> list = Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok");
	List<String> strList = filterStr(list, (s) -> s.length() > 3);
	
	for (String str : strList) {
		System.out.println(str);
	}
}
//需求:将满足条件的字符串,放入集合中
public List<String> filterStr(List<String> list, Predicate<String> pre){
	List<String> strList = new ArrayList<>();
	for (String str : list) {
		if(pre.test(str)){
			strList.add(str);
		}
	}
	return strList;
}

其他

在这里插入图片描述

方法引用

当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用

方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致

若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName

  • 对象::实例方法
Consumer<String> con1 = (x) -> System.out.println(x);
con1.accept("helloworld");
Consumer<String> con2 = System.out::println;
con2.accept("helloworld");
  • 类::静态方法
@Test
public void test4(){
	Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
	System.out.println("-------------------------------------");
	Comparator<Integer> com2 = Integer::compare;
}
  • 类::实例方法
@Test
public void test5(){
	BiPredicate<String, String> bp = (x, y) -> x.equals(y);
	System.out.println(bp.test("abcde", "abcde"));
	System.out.println("------------------------------");
	BiPredicate<String, String> bp2 = String::equals;
	System.out.println(bp2.test("abc", "abc"));
	System.out.println("------------------------------");
	Function<Employee, String> fun = (e) -> e.show();
	System.out.println(fun.apply(new Employee()));
	System.out.println("------------------------------");
	Function<Employee, String> fun2 = Employee::show;
	System.out.println(fun2.apply(new Employee()));
}

构造器引用

// 构造器的参数列表,需要与函数式接口中参数列表保持一致
@Test
public void test7(){
	Function<String, Employee> fun = Employee::new;
	BiFunction<String, Integer, Employee> fun2 = Employee::new;
}
@Test
public void test6(){
	Supplier<Employee> sup = () -> new Employee();
	System.out.println(sup.get());
	System.out.println("------------------------------------");
	Supplier<Employee> sup2 = Employee::new;
	System.out.println(sup2.get());
}
//数组引用
@Test
public void test8(){
	Function<Integer, String[]> fun = (args) -> new String[args];
	String[] strs = fun.apply(10);
	System.out.println(strs.length);
	System.out.println("--------------------------");
	Function<Integer, Employee[]> fun2 = Employee[] :: new;
	Employee[] emps = fun2.apply(20);
	System.out.println(emps.length);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值