目录
一. 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> {@Overridepublic 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>{@Overridepublic 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>() {@Overridepublic 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集合 |