Java8的一些新特性
文章目录
1、函数式接口
函数式接口:是Lambda表达式的基础,
什么是函数式接口?(它就是一个只有一个抽象方法的接口,通常我们会在这个接口上用一个
@FunctionalInterface
注解来验证这个接口是不是函数式接口)
2、Lambda表达式
2.1、介绍
它其实是一种新的java语法格式:用于实现函数式接口中的抽象方法的,
->
这就是lambda表达式的标识符,所以我们也叫lambda表达式为箭头函数,其实lambda在java中并不是以函数的方式存在的,java语言的核心理念是万物基于对象,所以lambda表达式的作用就被实现接口的一个匿名对象
2.2、案例
/**
* 函数式接口 即:该接口只有一个抽象方法
*/
@FunctionalInterface
public interface MyInterfaceTest {
public void showInfo(String str);
}
**
* Lambda表示使用:基于函数式接口的
*/
public class LambdaDemo1 {
/**
* 实现自定义的抽象接口
*/
@Test
public void test3() {
//传统方式
MyInterfaceTest interfaceTest = new MyInterfaceTest() {
@Override
public void showInfo(String str) {
System.out.println(str);
}
};
interfaceTest.showInfo("no give uo,no lost");
System.out.println("==================");
//lambda方式
//这里是很简洁的写法
MyInterfaceTest myInterfaceTest=str -> System.out.println(str);
myInterfaceTest.showInfo("no zuo no die");
}
2.3、案例讲解
上面就是一个很简单的lambda表达式的案例,函数式接口没什么好说的,传统的接口匿名内部类对象的写法也没什么好说的,这还是重点看一下lambda表达式为啥能这么写,有哪些规则
- 因为是函数式接口,接口中就这一个抽象方法,那么方法名是不是就默认就是它了,此时方法名就被省略了
- showInfo方法的形参有一个lambda中一个形参可以写
str->
或者(str)->
,但是如果是多个形参或者空参就必须要加()
。 - 返回值,这里showInfo没有返回值,所以直接写了一条输出语句,(如果表达式中只有一条语句需要执行,就都可以这么写,也不能在前面指定retrun)
- 方法体中的代码逻辑,因为只要一条语句需要执行所以省略了
{}和return的判断
由系统自己判断有没有返回,如果执行多条语句就必须添加{}
如果有返回值也最好是写上return
.
3、方法引用
3.1、介绍
方法引用其实是另外一种lambda的方式,本质上还是lambda 只是自己不再去实现函数式接口的方法,而是引用另外一个类的方法来实现接口 前提: 1.引用的方法的返回类型和形参类型以及个数必须一样(这只是针对,类调用静态方法和对象调用非静态的方法才有这么严格的要求) 2.引用的方法实现的功能必须和接口中需要实现的方法功能一样,不然你老婆叫你打酱油,你能打醋回去? 3.还有一种使用方式是,类调用非静态方法,这时候,对形参的个数要求就不那么严格了
3.2、案例
/**
* 对象调用非静态方法
*/
@Test
public void test1() {
//正常的lambda方式
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("今朝有酒今朝醉");
//方法引用,有一个类PrintStream 中有个void println(T t)方法也是输出语句,这就就用来代替我们自己的实现
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("天若有情天亦老");
}
/**
* 类调用静态方法
*/
@Test
public void test2() {
//正常的lambda方式
Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
int compare = comparator.compare(12, 13);
System.out.println(compare);
//方法引用
Comparator<Integer> comparator1 = Integer::compare;
int compare1 = comparator1.compare(12, 17);
System.out.println(compare1);
}
/**
* 类调用非静态方法
*/
@Test
public void test3() {
Comparator<String> comparator = String::compareTo;
System.out.println(comparator.compare("abc", "abd"));
Function<Person,String> stringSupplier = Person::getName;
Person person = new Person();
person.setName("海子");
System.out.println(stringSupplier.apply(person));
}
4、StreamApi
4.1、介绍
StreamApi是java8中一个很重要的更新,目前用的也很多用了就回不去了。
StreamApi是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,Stream讲的是计算!”注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
4.2、Stream流操作的三个步骤
1- 创建Stream
一个数据源(如:集合、数组),获取一个流
2- 中间操作
一个中间操作链,对数据源的数据进行处理
3- 终止操作(终端操作)
4.3案例
/**
* java8的StreamAPI 的学习案例
*/
public class StreamAPIDemo {
List<Person> personList = new ArrayList<>();
Person p1= new Person("胡歌",18,100.000);
Person p2= new Person("许嵩",16,109.000);
Person p3= new Person("刘亦菲",18,100.00000);
Person p4= new Person("薛之谦",20,10010.00);
Person p5= new Person("霍建华",18,100.0100);
Person p6= new Person("霍建华",18,100.0100);
@Test
public void test1(){
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);
personList.add(p5);
//创建流
Stream<Person> stream = personList.stream(); //还有parallelStream流这个是并行流,会并行去读取list里面的数据
//filter中间操作(过滤数据)forEach终止操作迭代遍历数据
stream.filter(p->p.getAge()>18).forEach(System.out::println);
System.out.println("====================");
//distinct中间操作去重
personList.stream().distinct().forEach(System.out::println);
System.out.println("====================");
//中间操作截断流从头开始到n
personList.stream().limit(3).forEach(System.out::println);
System.out.println("====================");
//中间操作 跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n) 互补
personList.stream().skip(3).forEach(System.out::println);
}
@Test
public void test2(){
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);
personList.add(p5);
personList.stream().map(person -> person.getAge()).forEach(System.out::println);
System.out.println("====================");
DoubleStream doubleStream = personList.stream().mapToDouble(p -> p.getMoney());
doubleStream.limit(3).forEach(System.out::println);
}
@Test
public void test3(){
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);
personList.add(p5);
System.out.println("=============================");
boolean b = personList.stream().allMatch(p -> p.getName() == "刘亦菲");
System.out.println(b);
System.out.println("=============================");
boolean b2 = personList.stream().anyMatch(p -> p.getName() == "刘亦菲");
System.out.println(b2);
System.out.println("=============================");
boolean b3 = personList.stream().noneMatch(p -> p.getName() == "haizi");
System.out.println(b3);
System.out.println("=============================");
Optional<Person> b4 = personList.stream().findFirst();
System.out.println(b4);
}
@Test
public void test4(){
personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);
personList.add(p5);
System.out.println("=============================");
List<String> list = personList.stream().map(p -> p.getName()).collect(Collectors.toList());
list.forEach(System.out::println);
String collect = personList.stream().map(person -> person.getName())
.collect(Collectors.joining("-","用户名:","所有都在这里了"));
System.out.println("=============================");
System.out.println(collect);
}
}
4.4、案例讲解
-
创建流
-
java8 中的Collection 接口被扩展,提供了两个获取流
的方法:
default Stream<E> stream()
: 返回一个顺序流
default Stream<E> parallelStream()
: 返回一个并行流 -
Java8 中的Arrays 的静态方法stream() 可以获取数组流:
static <T> Stream<T> stream(T[] array)
: 返回一个流重载形式,能够处理对应基本类型的数组:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)
-
通过Stream的of()
可以调用Stream类静态方法of(), 通过显示值创建一个 流。它可以接收任意数量的参数。
public static<T> Stream<T> of(T... values)
: 返回一个流-
创建无限流
可以使用静态方法
Stream.iterate()
和Stream.generate()
, 创建无限流。
迭代public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
生成
public static<T> Stream<T> generate(Supplier<T> s)
@Test public void test4() { // 迭代 // public static<T> Stream<T> iterate(final T seed, final // UnaryOperator<T> f) Stream<Integer> stream = Stream.iterate(0, x -> x + 2); stream.limit(10).forEach(System.out::println); // 生成 // public static<T> Stream<T> generate(Supplier<T> s) Stream<Double> stream1 = Stream.generate(Math::random); stream1.limit(10).forEach(System.out::println); }
-
Stream 的中间操作
-
筛选与切片
-
映射
-
排序
-
-
-
Stream的终止操作
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例
如:List、Integer,甚至是void 。流进行了终止操作后,不能再次使用。- 匹配与查找
2. 归约- 收集
4. Collectors工具类的方法
5、Optional类
5.1介绍
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional<T>
类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。 Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gnASnbSo-1596987873418)(assets/optional%E6%96%B9%E6%B3%95.png)]
5.2、案例
@Test
public void test1() {
Boy b = new Boy("张三");
Optional<Girl> opt = Optional.ofNullable(b.getGrilFriend());
// 如果女朋友存在就打印女朋友的信息
opt.ifPresent(System.out::println);
}
@Test
public void test2() {
Boy b = new Boy("张三");
Optional<Girl> opt = Optional.ofNullable(b.getGrilFriend());
// 如果有女朋友就返回他的女朋友,否则只能欣赏“嫦娥”了
Girl girl = opt.orElse(new Girl("嫦娥"));
System.out.println("他的女朋友是:" + girl.getName());
}
@Test
public void test3(){
Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
//判断opt中员工对象是否满足条件,如果满足就保留,否则返回空
Optional<Employee> emp = opt.filter(e -> e.getSalary()>10000);
System.out.println(emp);
}
@Test
public void test4(){
Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
//如果opt中员工对象不为空,就涨薪10%
Optional<Employee> emp = opt.map(e ->
{e.setSalary(e.getSalary()%1.1);return e;});
System.out.println(emp);
}
@Test
public void test3(){
Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
//判断opt中员工对象是否满足条件,如果满足就保留,否则返回空
Optional<Employee> emp = opt.filter(e -> e.getSalary()>10000);
System.out.println(emp);
}
@Test
public void test4(){
Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
//如果opt中员工对象不为空,就涨薪10%
Optional<Employee> emp = opt.map(e ->
{e.setSalary(e.getSalary()%1.1);return e;});
System.out.println(emp);
}