java8新特性

avatar
作者
猴君
阅读量:1

目录

一. lambda

1. 为什么要有lambda

2.功能接口 

3. 使用lambda的条件

二. Stream流

1. 获取流

1.1 将集合转为流

1.2 将数组转为流

1.3 将相同数据类型的数据转为流

1.4 将文件里的内容转为流

2. 中间操作

3. 终端操作


一. lambda

lambda:本质上就是将函数当做参数进行传递

在java8之前,函数是不能直接当做参数传递的,因为java是面向对象的语言,一切皆对象,所以在java8之前都是将函数包装在对象中进行传递,java8之后我们可以利用lambda将函数当做参数传递,并且书写简单,这也是java提供的语法糖之一

1. 为什么要有lambda

我们之前要在一些方法中传递接口/抽象类的对象时,要先自己写一个接口/抽象类的实现类,并实现里面的抽象方法,才能将接口/抽象类的对象当做参数进行传递.如下

public class Demo1 {     public static void main(String[] args) {         ArrayList<String> arrayList = new ArrayList<>();         arrayList.add("d");         arrayList.add("c");         arrayList.add("b");         arrayList.add("a");         arrayList.sort(new StringComparator1());         System.out.println();         System.out.println(arrayList);     } }
public class StringComparator1 implements Comparator<String> {      @Override     public int compare(String o1, String o2) {         return o1.compareTo(o2);     } }

我们这样虽然可以,但是这个类只在这个方法中被使用,没有必要向外提供一个类,这个类显得很多余,所以我们有了第一种优化,将该类定义为内部类,这样外面就不知道我们这里还定义了一个类

public class Demo1 {     public static void main(String[] args) {         ArrayList<String> arrayList = new ArrayList<>();         arrayList.add("d");         arrayList.add("c");         arrayList.add("b");         arrayList.add("a");         arrayList.sort(new StringComparator1());         System.out.println();         System.out.println(arrayList);     } }       static class StringComparator2 implements Comparator<String>     {          @Override         public int compare(String o1, String o2) {             return o1.compareTo(o2);         }     }

 这样虽然有了一定的优化,但是我们在调用该方法时还是要创建一个类来实现里面的抽象方法,有没有办法不用我们自己定义一个类,就可以实现该方法呢,下面进行第二次优化

public class Demo1 {     public static void main(String[] args) {         ArrayList<String> arrayList = new ArrayList<>();         arrayList.add("d");         arrayList.add("c");         arrayList.add("b");         arrayList.add("a");        //匿名内部类,为了减少类的创建        arrayList.sort(new Comparator<String>() {             @Override             public int compare(String o1, String o2) {                 return o1.compareTo(o2);             }         });         System.out.println();         System.out.println(arrayList);     } }

这里我们直接创建了一个匿名内部类的对象,注意不是创建了接口/抽象类的对象,而是创建了一个类这个类没有名字,但是实现了该接口/抽象类中的方法,我们称之为匿名内部类,这样虽然简化了很多,也不用我们自己去创建类,但是其实上述代码,我们只关心的是compare这个方法的方法体,而不是该匿名内部类对象,所以为了再一次书写方便,简单,我们引入了lambda表达式

public class Demo1 {     public static void main(String[] args) {         ArrayList<String> arrayList = new ArrayList<>();         arrayList.add("d");         arrayList.add("c");         arrayList.add("b");         arrayList.add("a");          //这是lambda表达式         arrayList.sort((a,b)->{             return a.compareTo(b);         });          System.out.println();         System.out.println(arrayList);     } }

2.功能接口 

功能接口:就是在定义接口时用@FunctionalInterface注解修饰的接口

作用:被@FunctionalInterface注解修饰的接口,在定义时,这个接口里只能有一个抽象方法,该注解会对接口进行检查,如果有两个或多个抽象方法编译器会报错

3. 使用lambda的条件

lambda的语法格式:

(参数列表)->{

方法体

}

参数列表是该接口有几个参数,这里就写几个形参,可以不写参数类型

方法体里面写重写该方法的内容

lambda的使用方法条件是该接口必须是功能接口(被@FunctionalInterface注解修饰的接口),即:该接口中只能有一个抽象方法.

一般在使用lambda时点到接口里面确定该接口是不是功能接口,如果是,再看有没有返回值以及有几个参数,这样就可以精确地使用lambda表达式了

为什么是功能接口才能使用lambda呢?

这是因为在使用lambda时只有函数体没有函数名,为了让编译器知道要调用哪个方法,我们在接口中就只定义一个抽象方法,这样编译器就知道调的肯定是这个方法,所以在使用lambda时必须确保该接口中只有一个抽象方法

二. Stream流

Stream流也是java为我们提供的语法糖,它用于将集合/数组转为流,利用流中提供的操作对集合/数组中的元素进行处理,处理完之后再转为集合/数组,也就是说Stream流类中是一种对集合/数组进行处理的操作,而具体的存储还是在集合/数组中

注意:

1.这里的Stream流不是IO流中的流

2.流的操作分为获取流,中间操作和终端操作

1. 获取流

1.1 将集合转为流

 Stream<Integer> stream = arrayList.stream();//把集合转为流

利用集合中的stream()方法就可以实现将集合转为流

1.2 将数组转为流

Integer[] array = new Integer[]{1,2,3,4}; Stream<Integer> stream1 = Arrays.stream(array);//把数组转为流

利用Arrays类中的stream()方法就可以将数组转为流

1.3 将相同数据类型的数据转为流

  Stream.of(1,2,3,4,5);//将同一类型的数据转为流(可变参数)

利用Stream类中的静态方法of(),该方法可以传入相同类型的数据,并且传入的形参是可变参数,即数据个数是任意的

1.4 将文件里的内容转为流

BufferedReader reader=new BufferedReader(new FileReader("stream.txt")); Stream<String> lineStream = reader.lines();

利用BufferedReader中的lines()方法将读到的一行内容转为流

2. 中间操作

中间操作就是将集合/数组转为流后,对数据进行的处理操作

filter(Predicate<? super T> predicate)对满足条件的数据进行过滤,满足留在流中,不满足去掉
sorted(Comparator<? super T>)对流中的元素进行排序,默认升序
distinct()去除流中的重复元素
limit(n)获取流中的n个元素
skip(n)跳过n个元素,配合limit(n)可实现分页
Integer[] array = new Integer[]{1,2,3,4,2,5}; Arrays.stream(array)    .skip(2)    .limit(2)    .sorted()    .distinct()    .forEach((e)->{       System.out.print(e+" ");                 });

3. 终端操作

终端操作就是将流转为集合/数组,或者是获得一个处理后的结果

forEach()对流中的元素进行遍历
toArray()将流中的元素倒入一个数组
Optional<T> Min(Comparator<? super T> )返回流中元素最小值
Optional<T> Max(Comparator<? super T> )返回流中元素最大值
long count()返回流中元素的总个数
Optional<T> Reduce(BinaryOperator<T>)返回流中所有元素的和
boolean anyMatch(Predicate<? super T>)只要流中有一个元素满足条件返回true,否则返回false
boolean allMatch(Predicate<? super T>)当流中所有元素满足条件返回true,否则返回false
findFirst()返回流中第一个元素
map将对象中的某个值放到一个新的集合/数组中
collect将流转为list,set,map集合

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!