lambda表达式
一个匿名函数 ,代码更简洁灵活。
格式:
-> 箭头操作符
箭头左边:lambda形参列表/其实就是接口中抽象方法的形参列表
箭头右边:lambda体 / 其实就是重写的抽象方法的方法体
注意: lambda 表达式针对的是==接口==
语法格式一:无参、无返回值
//非lambda表达式写法
Runnable l1=new Runnable() {
@Override
public void run() {
System.out.println("测试一");
}
};
l1.run();
//lambda表达式写法
Runnable l2=()->System.out.println("测试二");
l2.run();
语法格式二:需要一个参数、无返回值
//非lambda表达式写法
Consumer<String> consumer=new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("什么是快乐呢");
//lambda表达式写法
Consumer<String> consumer2=(String s)->System.out.println(s);
consumer2.accept("什么是快乐呢2");
语法格式三:数据类型可以省略,由编译器推断得出,称为类型推断
Consumer<String> consumer2=(s)->System.out.println(s);//将String S的String省去
consumer2.accept("什么是快乐呢2");
语法格式四:lambda 若只要一个参数,参数的小括号也可以省略
Consumer<String> consumer4=s->System.out.println(s);//将格式三中的()删去
consumer2.accept("什么是快乐呢4");
语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值
Comparator<Integer> comparable=(o1, o2)->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
语法格式六:当lambda 体只有一条语句的时候,return和大括号都可以省略
Comparator<Integer> comparable=(o1, o2)-> o1.compareTo(o2);
lambda 表达式本质:作为函数式接口(如果一个接口中只申明了一个抽象方法,则次接口称为函数式接口)的实例。
Stream API
使用Stream API可以对集合数据进行操作,就类似使用SQL语句执行数据库的查询
注意:
Stream本身不会存储数据
Stream不会改变源对象,而是返回一个持有新对象的Stream
Stream是延迟操作,需要用到结果时才执行。
Stream操作的三个步骤
-
创建Stream
一个数据源,获取一个流
创建方式一:通过集合创建
List<person> personList=new person().getListPersn(); Stream<person> stream = personList.stream();//返回一个顺序流的Stream Stream<person> personStream = personList.parallelStream();//返回一个并行流的Stream
创建方式二:通过数组创建Stream
int[] arr={1,2,3,4,5,6,7,8}; IntStream stream1 = Arrays.stream(arr);
创建方式三:通过Stream 的of()方法
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6);
-
中间操作
1筛选与切片
- filter()—接收lambda,从流中排除某些元素
stream.filter(e ->e.getAge()>24).forEach(System.out::println);//从人群中显示年龄大于24的
- limit(n) —截断流,使其元素
stream.limit(3).forEach(System.out::println);//从人群中显示3个人
- skip(n)跳过 元素返回一个去调前n个元素的流
stream.skip(3).forEach(System.out::println);//从人群中跳过前三个
- distinct() 筛选通过流生成元素的hashcode和equals()去除重复元素
stream.distinct().forEach(System.out::println);//从人群中去除重复的
2 映射
- map(Function f) 接收一个函数作为参数,将元素转换为其他形式或提取元素
List<String> list= Arrays.asList("aa","bb","cc","dd"); list.Stream().map(str->str.toUpperCase()).forEach(System.out::println);//将字母转为大写
flatMap(Function f) 接收一个函数作为参数,将流中的每个值换为另一个流,最后将流合并一个流
类似于 list.addAll()和list.add区别。将集合中嵌入的集合打开。
3排序
-
sorted() 自然排序
List<Integer> list=Array.asList(11,2,0,-8,-3,60); list.Stream().sorted().forEach(System.out::println);//对list排序 从小到大
-
sorted(comparator com) 定制排序
List<person> personList=new person().getListPersn(); personList.stream().sorted(e1,e2)->{ return Integer.compare(e1.getAge(),e2.getAge());//对对象按年龄排序 }.forEach(System.out::println);
-
终止操作
3.1匹配聚合操作
allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false findFirst:返回流中第一个元素 findAny:返回流中的任意元素 count:返回流中元素的总个数 max:返回流中元素最大值 min:返回流中元素最小值
使用代码:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true
Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1
long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1
3.2规约操作
Optional reduce(BinaryOperator accumulator):第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素;第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推。
T reduce(T identity, BinaryOperator accumulator):流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。
U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator combiner):在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。
//经过测试,当元素个数小于24时,并行时线程数等于元素个数,当大于等于24时,并行时线程数为16
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
Integer v = list.stream().reduce((x1, x2) -> x1 + x2).get();
System.out.println(v); // 300
Integer v1 = list.stream().reduce(10, (x1, x2) -> x1 + x2);
System.out.println(v1); //310
Integer v2 = list.stream().reduce(0,
(x1, x2) -> {
System.out.println("stream accumulator: x1:" + x1 + " x2:" + x2);
return x1 - x2;
},
(x1, x2) -> {
System.out.println("stream combiner: x1:" + x1 + " x2:" + x2);
return x1 * x2;
});
System.out.println(v2); // -300
Integer v3 = list.parallelStream().reduce(0,
(x1, x2) -> {
System.out.println("parallelStream accumulator: x1:" + x1 + " x2:" + x2);
return x1 - x2;
},
(x1, x2) -> {
System.out.println("parallelStream combiner: x1:" + x1 + " x2:" + x2);
return x1 * x2;
});
System.out.println(v3); //197474048
3.3收集操作
collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。
Collector<T, A, R> 是一个接口,有以下5个抽象方法:
Supplier< A > supplier():创建一个结果容器A
BiConsumer<A, T> accumulator():消费型接口,第一个参数为容器A,第二个参数为流中元素T。
BinaryOperator< A > combiner():函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各 个子进程的运行结果(accumulator函数操作后的容器A)进行合并。
Function<A, R> finisher():函数式接口,参数为:容器A,返回类型为:collect方法最终想要的结果R。
Set characteristics():返回一个不可变的Set集合,用来表明该Collector的特征。有以下三个特征:
CONCURRENT:表示此收集器支持并发。
UNORDERED:表示该收集操作不会保留流中元素原有的顺序。
IDENTITY_FINISH:表示finisher参数只是标识而已,可忽略。