最近在工作中看到同事在用java8新特性,今天就给大家带来java8新特性的一些简要介绍,如有不足,敬请指正。
一、java8新特性简介
- Lambda表达式
- 函数式接口
- 方法引用与构造器引用
- Stream API
- 接口中的默认方法与静态方法
- 新时间日期API
- 其他特性
在数据结构这块,比如java8对HashMap进行了优化,在以前的基础上加入了红黑树,速度更快,提高了效率。最大化减少空指针异常 Optional,在内存这块也做了优化处理,感兴趣的小伙伴可以详细了解下。这里不再赘述。
其中最重要的还是我们的Lambda表达式和Stream API。
二、入门小案例
先来体会一下Lambda表达式和Stream API:我们在开发过程中经常遇到这样的需求:找出年龄大于20岁的对象。使用了Lambda表达式和Stream API后可以极大减少代码量。提高开发效率。
实体类
package com.rrss.test;
/**
* @author lzx
*
* 实体类
*/
public class People {
private String name;
private int age;
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 People() {
super();
}
public People(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "People [name=" + name + ", age=" + age + "]";
}
}
测试类
package com.rrss.test;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
/**
* @author lzx
*
*/
public class LambdaTest {
@Test
public void testLambda() {
List<People> peoples = Arrays.asList(
new People("张三", 18),
new People("李四", 25),
new People("王五", 30)
);
//找出年龄大于20的对象
peoples.stream()
.filter((t) ->t.getAge()>20)
.forEach(System.out::println);
System.out.println("------华丽分割线------");
//找出所有对象的名字
peoples.stream()
.map(People::getName)
.forEach(System.out::println);
}
}
测试结果 |
---|
![]() |
由此看出Lambda表达式和Stream ApI 是很强大的,减少很多的冗余代码。 |
接下来我们来详解Lambda表达式
三、Lambda表达式
下面我们来详细介绍Lambda表达式基础语法。
需要注意的是,Lambda表达式需要函数式接口的支持。
3.1 什么是函数式接口
函数式接口:接口中只有一个抽象方法的接口称为函数式接口。我们可以用@FunctionalInterface来修饰接口,检查接口是否是函数式接口。
package com.rrss.test;
/**
* @author lzx
*
*/
@FunctionalInterface
public interface LambdaInterface {
void show(int name);
}
以上就是一个函数式接口,如果在此接口中继续增加抽象方法则会报错(@FunctionalInterface来修饰)。
3.2 基础语法
在java8中引入了一个新的操作符“->”,称为箭头操作符或者Lambda操作符,此符号将表达式拆分成两部分。
左侧部分为Lambda表达式参数列表,右侧部分为表达式中需要执行的功能。
语法一、无参数,无返回值
package com.rrss.test;
import org.junit.Test;
/**
* @author lzx
*
*/
public class LambdaGrammer {
@Test
public void test1() {
// 之前写法
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello World");
}
};
r1.run();
// Lambda表达式
Runnable r = () -> System.out.println("Hello Lambda");
r.run();
}
}
执行结果 |
---|
![]() |
语法二、有参数(1个),无返回值
先看Consumer接口 |
---|
![]() |
@Test
public void test2() {
Consumer<String> consumer = (x) -> System.out.println(x);
consumer.accept("Hello world");
}
测试结果 |
---|
![]() |
语法三、若有参数(1个),小括号可省略不写
@Test
public void test3() {
Consumer<String> consumer = x -> System.out.println(x);
consumer.accept("Hello world");
}
测试结果 |
---|
![]() |
语法四、参数2个以上,有返回值,有多条语句
@Test
public void test4() {
Comparator<Integer> comparable = (x, y) -> {
System.out.println("语法4");
return Integer.compare(x, y);
};
}
语法五、Lambda体中只有一条语句,return和大括号都可以省略不写
@Test
public void test5() {
Comparator<Integer> comparable = (x, y) -> Integer.compare(x, y);
}
语法六、Lambda表达式中的参数列表的数据类型可以省略不写,JVM会坐类型推断
3.3 应用:对一个数进行运算
- 自定义一个接口
package com.rrss.test;
/**
* @author lzx
*
*/
@FunctionalInterface
public interface MyInterface {
int excute(int num);
}
- 测试类
package com.rrss.test;
import org.junit.Test;
/**
* @author lzx
*
*/
public class LambdaPractice {
@Test
public void testLambda() {
int num = calc(10, (x) -> x + 100);
System.out.println("加法运算:" + num);
}
@Test
public void testLambdaFun() {
int num = calc(10, (x) -> x * 100);
System.out.println("乘法运算:" + num);
}
public int calc(int num, MyInterface data) {
return data.excute(num);
}
}
未完待续...