lambda整理

Stream 中的 Reduce 方法:根据一定的规则将Stream中的元素进行计算后返回一个唯一的值

函数式接口

Java 8 的库设计师在 java.util.function 包中引入了几个新的函数式接口.
Predicate, Consumer 和 Function

java.util.function.Predicate
接口定义了一个名叫 test() 的抽象方法, 它接受泛型 T 对象, 并返回一个 boolean .
boolean test(T t)
T -> boolean

java.util.function.Consumer
定义了一个名叫 accept() 的抽象方法,它接受泛型T 的对象,没有返回(void )。
你如果需要访问类型 T 的对象,并对其执行某些操作,就可以使用这个接口.
T -> void

Function 接口 java.util.function.Function<T, R>
接口定义了一个叫作 apply 的方法,它接受一个泛型 T 的对象,并返回一个泛型 R 的对象。
如果你需要定义一个 Lambda,将输入对象的信息映射到输出,就可以使用这个接口.
T -> R

Supplier

// 构造函数引用指向默认的Apple()构造函数
Supplier<Apple> c1 = Apple::new;

// 调用Supplier的get方法将产生一个新的Apple对象
Apple a1 = c1.get();

排序

// 多个字段排序
Comparator<People> com
    = Comparator.comparing(People::getUpdateDate, Comparator.reverseOrder())
    // 枚举值 默认是按照 java.lang.Enum.ordinal()方法 排序的.即在枚举类中声明的顺序排序
    .thenComparing(People::getMyEnum, Comparator.reverseOrder())
    .thenComparing(People::getId, Comparator.reverseOrder());

list.sort(com);

方法引用

1.Lambda表达式调用静态方法
2.(a, b) -> a.xxx(b)
3.构造器引用

// 方法引用
// 1.Lambda表达式调用静态方法
Function<String, Integer> stringToInteger = (String s) -> Integer.parseInt(s);
// 改为 方法引用
Function<String, Integer> stringToInteger1 = Integer::parseInt;

// 2.Lambda使用其第一个参数,调用其contains 方法。由于第一个参数是List 类型的
// (a, b) -> a.xxx(b)
BiPredicate<List<String>, String> contains = (list, element) -> list.contains(element);
// 改为 方法引用
BiPredicate<List<String>, String> contains1 = List::contains;

// 3.构造器引用
Supplier<Apple> c0 = () -> new Apple();    // ←─利用默认构造函数创建Apple的Lambda表达式
Apple a0 = c0.get();   //  ←─调用Supplier的get方法将产生一个新的Apple

// === 改写后
// 构造函数引用指向默认的Apple()构造函数
Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get(); // 调用Supplier的get方法将产生一个新的Apple对象

集合

1.移除元素

list.removeIf(person -> {
    return person.getName() == null;
});
list.stream() // 从menu获得流(菜肴列表)
.filter(d -> d.getCalories() < 400) // 建立操作流水线:首先选出低热量的菜肴
.sorted(comparing(Dish::getCalories)) // 按照热量排序
.map(Dish::getName) // 获取 Dish.菜名
.collect(toList()); // 将结果保存在另一个 List 中

创建流的方式

// Stream.of
// 1.由值创建流
// 使用静态方法Stream.of ,通过显式值创建一个流。它可以接受任意数量的参数。
Stream<String> stream = Stream.of("Java 8", "Lambdas", "In", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);

// Stream.empty
// 使用empty 得到一个空流
Stream<String> emptyStream = Stream.empty();

// Arrays.stream
// 2.由数组创建流
int[] numbers = {2, 3, 5, 7, 11, 13};
System.out.println(Arrays.stream(numbers).sum());

// 3.由文件创建流
long uniqueWords = 0;
// 你可以使用Files.lines 得到一个流,其中的每个元素都是给定文件中的一行
try (Stream<String> lines =
            Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) { // ←─流会自动关闭
    uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" "))) // ←─生成单词流
        .distinct()    // ←─删除重复项
        .count();    // ←─数一数有多少各不相同的单词
    } catch (IOException e) {
        //   ←─如果打开文件时出现异常则加以处理
    }

// 4.由函数生成流:创建无限流
// Stream API提供了两个静态方法来从函数生成流:Stream.iterate 和Stream.generate 。
// 这两个操作可以创建所谓的无限流 :不像从固定集合创建的流那样有固定大小的流。
// 由iterate 和generate 产生的流会用给定的函数按需创建值,因此可以无穷无尽地计算下去!
// 一般来说,应该使用limit(n) 来对这种流加以限制,以避免打印无穷多个值。
// Stream.iterate
Stream.iterate(0, n -> n + 2)
    .limit(10)
    .forEach(System.out::println);

.filter() 过滤出

查找和匹配

anyMatch() 方法可以回答“流中是否有一个元素能匹配给定的谓词”

allMatch() 所有都匹配

noneMatch() 没有一个匹配

findAny() 方法将返回当前流中的任意元素,返回 Optional

map() 和 flatMap()

Reducing

// 求和,方式2
int sum = numbers.stream().reduce(0, (a, b) -> a + b);

// 在Java 8中,Integer 类现在有了一个静态的 sum 方法来对两个数求和
int sum2 = numbers.stream().reduce(0, Integer::sum);

// 相乘
int product = numbers.stream().reduce(1, (a, b) -> a * b);

// 最大值
int max2 = numbers.stream().reduce(0, Integer::max);

// 最小值
// 不传初值,返回 Optional
Optional<Integer> min = numbers.stream().reduce(Integer::min);
min.ifPresent(System.out::println);

int calories = menu.stream()
        .map(Dish::getCalories)
        .reduce(0, Integer::sum);

Grouping 分组

grouping 分组 返回的一定是 key -> List 结构.
与 map() 区别, map 返回 key -> value 结构.

menu.stream().collect(groupingBy(Dish::getType))

// mapping() 方法接受两个参数:一个函数对流中的元素做变换,另一个则将变换的结果对象收集起来
menu.stream().collect(groupingBy(Dish::getType, mapping(Dish::getName, toList())));

// 自定义分组逻辑
menu.stream().collect(
    groupingBy(dish -> {
        if (dish.getCalories() <= 400) {
            return CaloricLevel.DIET;
        } else if (dish.getCalories() <= 700) {
            return CaloricLevel.NORMAL;
        } else {
            return CaloricLevel.FAT;
        }
    }));

// TODO 待补充剩余场景    

Partitioning 分区

分区是分组的特殊情况:由一个谓词(返回一个布尔值的函数)作为分类函数,它称分区函数。
分区函数返回一个布尔值,这意味着得到的分组Map 的键类型是Boolean ,于是它最多可以分为两组——true 是一组,false 是一组。

menu.stream().collect(partitioningBy(Dish::isVegetarian))

Reducing

// 可以用 reducing() 方法创建的收集器来计算你菜单的总热量
// reducing() 需要三个参数。
// 第一个参数: 初始值. 是归约操作的起始值,也是流中没有元素时的返回值,所以很显然对于数值和而言0 是一个合适的值。
// 第二个参数: 转换函数,将菜肴转换成一个表示其所含热量的int 。
// 第三个参数: 是一个 BinaryOperator ,将两个项目累积成一个同类型的值。这里它就是对两个int 求和。
return menu.stream().collect(reducing(0, Dish::getCalories, (Integer i, Integer j) -> i + j));

// 可以被替换成 map().reduce()形式

Summarizing 统计

TODO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值