学习Java 8的核心新特性:Lambda(匿名函数)、流

一、Lambda——匿名函数
等效方法引用

Lambda表达式 等效方法引用
(String s) -> System.out.println(s) System.out::println
((str, i) -> str.substring(i) String::substring
() -> Thread.currentThread().dumpStack() Thread.currentThread()::dumpStack
函数式接口就是只定义一个抽象方法的接口。
Lambda的基本语法是:
(parameters) -> expression
(parameters) -> { statements; }

举例:

① Lambda表达式具有一个 String 类型的参数并返回一个 int 。
Lambda没有 return 语句,因为已经隐含了 return

(String s) -> s.length()

② Lambda表达式有一个Apple 类 型 的参数并返回一个 boolean 

(Apple a) -> a.getWeight() > 150

Lambda表达式具有两个 int 类型的参数而没有返回值( void 返回)。
注意Lambda表达式可以包含多行语句,这里是两行。

(int x, int y) -> {
   System.out.println("Result:");
   System.out.println(x+y);
}

Lambda表达式没有参数,返回一个int 。

() -> 42

Lambda表达式具有两个 Apple 类型的参数,返回一个 int :比较两个 Apple 的重量。

(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

对于,对参数有修改,或者修饰,则不能使用方法引用,需要输入完成的lambda表达式

list.forEach((String s) -> System.out.println("*" + s + "*"));
list.forEach( s -> System.out.println("*" + s + "*"));

lambda表达式有个限制,不能在lambda内部修改定义在域外的变量。

List<Integer> primes = Arrays.asList(new Integer[]{2, 3,5,7});
int factor = 2;
primes.forEach(element -> { factor++; });//不能执行
//可以执行,lambda只能访问它,不可以改变它
primes.forEach(element -> { System.out.println(factor*element); });

二、流操作(Stream)

List  《== 转换 ==》  Stream

Stream<String> stream = list.stream();
List<String> list = stream.collect(Collectors.toList());

常用流的构建:

数组构建
int[] arr = {1, 2, 3, 4, 5};
IntStream intStream = Arrays.stream(arr);

空流:
Stream<Object> emptyStream = Stream.empty();

静态方法Stream.of可以显式值创建一个流。它可以接受任意数量的参数。例如,以下代码直接使用Stream.of创建了一个字符串流:
Stream<String> s = Stream.of("Java", "JavaScript", "C++", "Ruby");

List<String> list = Arrays.asList("Java", "JavaScript", "python", "PHP", "C#", "Golang", "Swift");
list.stream()
    .filter(s -> s.startsWith("J"))
    .map(String::toUpperCase)
    .forEach(System.out::println);
流的使用一般包括三件事情:

一个数据源(如集合)来执行一个查询;
一个中间操作链,形成一条流的流水线;
一个终端操作,执行流水线,并能生成结果。

下表列出了流中常见的中间操作和终端操作:
学习Java 8的核心新特性:Lambda(匿名函数)、流
下面详细介绍这些操作的使用。除了特殊说明,默认使用下面这个集合作为演示:

List<String> list = Arrays.asList("Java", "JavaScript", "python", "PHP", "C#", "Golang", "Swift", "C++", "Ruby");

常用中间操作

filter
Streams接口支持·filter方法,该方法接收一个Predicate<T>,函数描述符为T -> boolean,用于对集合进行筛选,返回所有满足的元素:

list.stream()
    .filter(s -> s.contains("#"))
    .forEach(System.out::println);
    
结果输出2 4
distinct
distinct方法用于排除流中重复的元素,类似于SQL中的distinct操作。比如筛选中集合中所有的偶数,并排除重复的结果:

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
       .filter(i -> i % 2 == 0)
       .distinct()
       .forEach(System.out::println);
       
结果输出JavaScript。
limit
limit(n)方法返回一个长度不超过n的流,比如下面的例子将输出Java JavaScript python:

list.stream()
    .limit(3)
    .forEach(System.out::println);
map
map方法接收一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素。如:

list.stream()
    .map(String::length)
    .forEach(System.out::println);
       
结果输出4 10 6 3 2 6 5 3 4。

终端操作:

collect
collect方法用于收集流中的元素,并放到不同类型的结果中,比如List、Set或者Map。举个例子:

List<String> filterList = list.stream()
        .filter(s -> s.startsWith("J")).collect(Collectors.toList());
        
如果需要以Set来替代List,只需要使用Collectors.toSet()就好了。
count
count方法用于统计流中元素的个数,比如:

list.stream().count(); // 9
forEach
forEach用于迭代流中的每个元素,最为常见的就是迭代输出,如:

list.stream().forEach(System.out::println);
anyMatch    allMatch   noneMatch
anyMatch方法用于判断流中是否有符合判断条件的元素,返回值为boolean类型。比如判断list中是否含有SQL元素:

list.stream()
    .anyMatch(s -> "SQL".equals(s)); // false
上一篇:函数式编程-------概念基础部分


下一篇:20210416----java---list&map