赞
踩
我的理解匿名实现类的简写,也可以称为闭包
作用:
例:
类型 变量 = (参数类型 param1, 参数类型 param2 ...)->{实现};
Runnable runnable = () -> System.out.println("创建Runnable");
Lambda表达式只能引用标记了final的外层局部变量,这就是说不能在lambda内部修改定义在域外的局部变量,否则会编译错误。
可以直接在 lambda 表达式中访问外层的局部变量,lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
- Consumer<T> 消费型接口(无返回值,有去无回)
- void accept(T t);
-
- Supplier<T> 供给型接口
- T get();
-
- Function<T,R> 函数型接口
- R apply(T t);
-
- Predicate<T> 断言型接口
- boolean test(T t);
JDK8引入了函数式编程风格,通过流对集合和数组进行处理
主要用到两个类Stream类和Collectors类
Stream有如下三个操作步骤:
创建Stream:从一个数据源,如集合、数组中获取流。
要注意的是,对流的操作完成后需要进行关闭操作(或者用JAVA7的try-with-resources)。
中间操作:filter、limit、skip、distinct、map、flagMap、sorted、peek
终止操作:foreach、count、allMatch、anyMatch、noneMatch
- // 1、终止操作-foreach(Consumer<? super T> action) 遍历
- // personList.forEach(person -> System.out.println(person.getName()));
- // personList.forEach(person -> System.out.println(person));
- // personList.stream().forEach(System.out::println);
- // personList.forEach(System.out::println);
- integerList.forEach(i -> {
- if(i == 3){
- return;
- }
- System.out.println(i);
- });
- long count1 = personList.stream().count();
- System.out.println(count1);
- long count2 = personList.stream().filter(p -> ('F') == p.getSex()).count();
- System.out.println(count2);
boolean b = personList.stream().allMatch(p -> p.getAge()>= 18);
boolean b = personList.stream().anyMatch(p -> "赵八".equals(p.getName()));
boolean b = personList.stream().noneMatch(p -> "赵八123".equals(p.getName()));
- Person person1 = personList.stream().findFirst().get();
- Person person2 = personList.stream().findFirst().orElse(null);
- // Optional 类的应用
- Person person1 = personList.stream().findAny().get();
- Person person2 = personList.stream().findAny().orElse(null);
- // Optional 类的应用
- Comparator<Integer> comparator = (o1, o2) -> {
- if (o1.intValue() == o2.intValue()) {
- return 0;
- }
- if (o1 > o2) {
- return 1;
- }
- return -1;
- };
- //Integer integer = integerList.stream().max(comparator).get();
- Integer integer = integerList.stream().max(Integer::compareTo).get();
- System.out.println(integer);
-
- Comparator<Person> comparator1 = (person1, person2) -> {
- if (person1.getAge().intValue() == person2.getAge()) {
- return 0;
- }
- if (person1.getAge() > person2.getAge()) {
- return 1;
- }
- return -1;
- };
- Person person1 = personList.stream().max(comparator1).get();
- System.out.println(person1);
-
- // Person类实现compareTo方法
- Person person2 = personList.stream().max(Person::compareTo).get();
- System.out.println(person2);
- // Optional 类的应用
Integer min = integerList.stream().min(Integer::compare).get();
- // BinaryOperator<T> extends BiFunction<T,T,T>
- // R apply(T t, U u);
-
- // 1、Optional<T> reduce(BinaryOperator<T> accumulator);
- // 对Stream中的数据通过累加器accumulator迭代计算,最终得到一个Optional对象
- BinaryOperator<Integer> binaryOperator = (a, b) ->{
- a += b;
- return a;
- };
- Integer result = integerList.stream().reduce(binaryOperator).get();
- System.out.println(result);
-
- // 2、T reduce(T identity, BinaryOperator<T> accumulator);
- // 初始值identity,通过累加器accumulator迭代计算Stream中的数据,得到一个跟Stream中数据相同类型的最终结果
- Integer reduce = integerList.stream().reduce(100, binaryOperator);
- System.out.println(reduce);
-
- // 3、<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
- // BiFunction的三个泛型类型分别是
- // U
- // ? super T
- // U
- // 参考BiFunction函数式接口 R apply(T t, U u);
- // 方法定义可以知道,累加器累加器通过类型为 U 和 ? super T 的两个输入值计算得到一个U类型的结果返回。
- // 也就是说这种reduce方法,提供一个不同于Stream中数据类型的初始值,通过累加器规则迭代计算Stream中的数据,最终得到一个同初始值同类型的结果
- // reduce的第三个参数是在使用parallelStream的reduce操作时,合并各个流结果的
- // 由于所有使用并行流 parallelStream 的地方都是使用同一个 Fork-Join 线程池,而线程池线程数仅为 cpu 的核心数。
- // 切记,如果对底层不太熟悉的话请不要乱用并行流 parallelStream(尤其是你的服务器核心数比较少的情况下)
- List<Integer> integers = new ArrayList<>();
- integers.add(100);
- Integer reduce1 = integerList.parallelStream().reduce(0, (a, b) -> {
- a += b;
- return a;
- }, (a, b) -> {
- a += b;
- return a;
- });
- System.out.println(reduce1);
- // Optional 类的应用
collect 收集 将流转换为其他形式,接收一个Collectors接口实现 ,用于给Stream中汇总的方法
- // 1、toList
- List<Person> collect1 = personList.stream().collect(Collectors.toList());
-
- // 2、toSet
- Set<Person> collect2 = personList.stream().collect(Collectors.toSet());
-
- // 3、toMap
- // 3.1
- // Map<String, Person> collect3 = personList.stream().collect(Collectors.toMap(Person::getName, Function.identity()));
- // 假如key存在重复值,则会报错Duplicate key xxx, 解决方案是
- // 只取后一个key及value:
- Map<String, Person> collect31 = personList.stream().collect(Collectors.toMap(Person::getName, Function.identity(), (oldValue,newValue) -> newValue));
- // 只取前一个key及value:
- Map<String, Person> collect32 = personList.stream().collect(Collectors.toMap(Person::getName, Function.identity(), (oldValue,newValue) -> oldValue));
- // 假如存在key重复,两个value可以这样映射到同一个key
- Map<String, String> map = personList.stream().collect(Collectors.toMap(Person::getName,Person::getCountry,(e1,e2)->e1+","+e2));
-
- // 3.2取对象的属性作为k-v
- //Map<String, Integer> collect33 = personList.stream().collect(Collectors.toMap(Person::getName, Person::getAge));
- // 防止name重复
- Map<String, Integer> collect34 = personList.stream().collect(Collectors.toMap(Person::getName, Person::getAge,(oldValue,newValue)-> newValue));
- // 注意:value可以为空字符串但不能为null,否则会报空指针,解决方案:
- Map<String, Integer> collect35 = personList.stream().collect(Collectors.toMap(Person::getName, p-> p.getAge() == null ? 0 : p.getAge(),(oldValue, newValue)-> newValue));
-
- // 4、Collectors.groupBy 聚合 -> map(k,List)
- Map<String, List<Person>> collect4 = personList.stream().collect(Collectors.groupingBy(Person::getName));
- // 5、Collectors.groupBy 聚合统计 -> map(k,count)
- Map<String, Long> collect5 = personList.stream().collect(Collectors.groupingBy(Person::getName, Collectors.counting()));
- Map<String, Long> collect6 = stringList.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
-
- //把List1和List2中id重复的Student对象的name取从list1中出来:
- List<Student> list1 = studentList;
- List<Student> list2 = Arrays.asList(new Student(1L,"张飞"),new Student(102L,"赵子龙"));
- Map<Long, Student> map2 = list2.stream().collect(Collectors.toMap(Student::getId,Function.identity()));
- System.out.println(map2);
- List<String> list3 = list1.stream()
- .map(Student::getId)// Long
- .filter(map2::containsKey) //Long
- .map(map2::get) // Student
- .map(Student::getName)
- .collect(Collectors.toList());
- System.out.println(list3);// 输出 [张飞]
- String output1 = String.join(",", stringList);
- System.out.println(output1);
- String output2 = stringList.stream().collect(Collectors.joining(","));
- System.out.println(output2);
- String[] arr = {"a","b","c"};
- String collect = Arrays.stream(arr).collect(Collectors.joining(",", "{", "}"));
- System.out.println(collect);
- String collect2 = integerList.stream().map(i -> String.valueOf(i * i)).collect(Collectors.joining(","));
- System.out.println(collect2);
- int sumAge = personList.stream().mapToInt(Person::getAge).sum();
- System.out.println(sumAge);
-
- IntStream intStream = personList.stream().mapToInt(Person::getAge);
- IntSummaryStatistics stats = intStream.summaryStatistics();
- System.out.println("age中最大的数 : " + stats.getMax());
- System.out.println("age中最小的数 : " + stats.getMin());
- System.out.println("age所有数之和 : " + stats.getSum());
- System.out.println("age平均数 : " + stats.getAverage());
-
- //BigDecimal decimal = leaderData.stream()
- // .map(DailyCollectionRateResponse::getTotalPaidAmount)
- // .filter(Objects::nonNull)
- // .reduce(BigDecimal::add)
- // .orElse(BigDecimal.ZERO);
personList.stream().filter(p -> ('M')==p.getSex()).forEach(System.out::println);
personList.stream().limit(4).forEach(System.out::println);
personList.stream().skip(4).forEach(System.out::println);
- // 1、Integer去重
- List<Integer> integers = Arrays.asList(1, 2, 3, 3, 5, 5, 6, 6, 7, 8);
- List<Integer> collect1 = integers.stream().distinct().collect(Collectors.toList());
- System.out.println(collect1);
- // 2、 String去重
- List<String> collect2 = stringList.stream().distinct().collect(Collectors.toList());
- System.out.println(collect2);
-
- // 3、 Stream.distinct() with List of Objects, 去重的的是实例对象,
- // 3.1 全字段去重需要重写equals()和hashCode(),distinct不提供按照属性对对象列表进行去重的直接实现。它是基于hashCode()和equals()工作的。
- System.out.println(personList.size());
- personList.stream().distinct().forEach(System.out::println);
- long count1 = personList.stream().distinct().count();
- System.out.println(count1);
-
- // 3.2 部分字段去重
- // 如果我们想要按照对象的部分属性去重,我们可以通过其它方法来实现。如下三种代码段所示:
- // 3.2.1 filter单属性去重, 原理是用来map
- personList.stream().filter(distinctByKey(Person::getName)).forEach(System.out::println);
- personList.stream().filter(new Predicate<>() {
- final Map<Object, Boolean> seen = new ConcurrentHashMap<>();
- @Override
- public boolean test(Person t) {
- return seen.putIfAbsent(t.getName(), Boolean.TRUE) == null;
- }
- }).forEach(System.out::println);
- personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new)).forEach(System.out::println);
-
-
- // 3.2.2多属性去重
- personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new)).forEach(System.out::println);
- personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(f -> f.getName() + f.getAge()))), ArrayList::new)).forEach(System.out::println);
-
- public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
- Map<Object, Boolean> seen = new ConcurrentHashMap<>();
- return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
- }
操作采用一个方法,该方法针对输入流中的每个值调用,并生成一个结果值,该结果值返回至stream
- List<String> nameList = personList.stream().map(Person::getName).collect(Collectors.toList());
- List<Person> collect = personList.stream().map(person -> new Person(person.getName(), person.getAge())).collect(Collectors.toList());
- List<Pair> collect = personList.stream().map(p -> new Pair(p.getName(), p.getAge())).collect(Collectors.toList());
- List<Integer> numbers1 = Arrays.asList(1, 2, 3);
- List<Integer> numbers2 = Arrays.asList(3, 4);
- // 1、flatMap升维度,笛卡尔积
- List<int[]> pairs = numbers1.stream().flatMap(x -> numbers2.stream().map(y -> new int[] { x, y })).collect(Collectors.toList());
- for (int[] pair : pairs) {
- System.out.println(Arrays.toString(pair));
- }
- // 2、一维度合并
- List<String> fun1 = Arrays.asList("one", "two", "three");
- List<String> fun2 = Arrays.asList("four", "five", "six");
- Stream.of(fun1,fun2).flatMap(List::stream).forEach(System.out::println);
sorted()--自然升序排序(Comparable), 如何降序 reviersed
- // 1、升序
- integerList.stream().sorted().forEach(System.out::println);
- // 2、降序, 需要自定义comparator
- integerList.stream().sorted(Comparator.comparing(Integer::intValue).reversed()).forEach(System.out::println);
-
- // 2、sorted(Comparator com)--定制排序(Comparator)
- personList.stream().sorted(Comparator.comparing(Person::getAge)).forEach(System.out::println);
- personList.stream().sorted(Comparator.comparing(Person::getAge).reversed()).forEach(System.out::println);
-
- // 先根据age排, 再根据name排
- personList.stream().sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getName)).forEach(System.out::println);
- personList.stream().sorted(Comparator.comparing(Person::getAge).reversed().thenComparing(Person::getName).reversed()).forEach(System.out::println);
peek的设计初衷就是在流的每个元素恢复运行之前的时候插入一个执行操作. 它不想forEach那样恢复整个流的运行操作. 而是在一个元素上完成操作之后, 它只会将操作顺承到流水线的下一个操作. 它能够将中间变量的值输出到日志. 有效的帮助我们了解流水线的每一步操作的输出值.
- List<Integer> list1 = Arrays.asList(4, 7, 9, 11, 12);
- list1.stream()
- .map(x -> x + 2) // 各项+2
- .filter(x -> x % 2 != 0)// 取模不为0的
- .limit(2) // 只取前两个
- .forEach(System.out::println);
- //可以很明显的看出, 一旦调用了forEach操作, 整个流就会恢复运行.并不能很好的帮助我们了解Stream流水线中的每个操作(如:map,filter,limit等)产生的输出.
- List<Integer> list2 = Arrays.asList(4, 7, 9, 11, 12);
- list2.stream()
- .peek(x -> System.out.println("stream: " + x))
- .map(x -> x + 2)
- .peek(x -> System.out.println("map: " + x))
- .filter(x -> x % 2 != 0)
- .peek(x -> System.out.println("filter: " + x))
- .limit(2)
- .peek(x -> System.out.println("limit: " + x))
- .collect(Collectors.toList());
peek和map的区别
注意:peek对一个对象进行操作的时候,对象不变,但是可以改变对象里面的值.如下:
- Stream.of(new Person("001",15),new Person("002",16))
- .peek(p -> p.setSex('0'))
- .forEach(System.out::println);
peek方法接收一个Consumer的入参. 了解λ表达式的应该明白 Consumer的实现类应该只有一个方法,该方法返回类型为void. 它只是对Stream中的元素进行某些操作,但是操作之后的数据并不返回到Stream中,所以Stream中的元素还是原来的元素.
map的定义
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
map方法接收一个Function作为入参. Function是有返回值的, 这就表示map对Stream中的元素的操作结果都会返回到Stream中去.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。