背景
JDK 11 已经快要来了,所以 JDK 的新特征还是要及时学习的。
先从 JDK 8 的特征来入手吧。
本文先记录一下 lambda 表达式的学习。
另外,在 ClickHouse 的学习中,发现 ClickHouse 也支持了 lambda 表达式做为 SQL 的一部分。
所以 lambda 表达式已经是常识了。
lambda 表达式例子
创建线程
public class MainLambda {
public static void main(String[] args) {
Thread thread = new Thread(() -> System.out.println("Hello world!"));
thread.start();
}
}
输出
Hello world!
排序
public class MainLambda {
public static void main(String[] args) {
List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));
System.out.println(list);
}
}
输出
[a, b, c]
转换成大写
public class MainLambda {
public static void main(String[] args) {
List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
List<String> newlist = list.stream().map(s -> s.toUpperCase()).collect(Collectors.toList());
System.out.println(newlist);
}
}
输出
[B, C, A]
遍历每个元素
import java.util.Arrays;
import java.util.List;
public class MainLambda {
public static void main(String[] args) {
List<String> list = Arrays.asList(new String[] { "b", "c", "a" });
list.stream().forEach(s -> System.out.println(s.toUpperCase()));
}
}
输出
B
C
A
lambda 表达式语法
一般语法
(Type1 param1, Type2 param2, ..., TypeN paramN) -> {
statment1;
statment2;
//.............
return statmentM;
}
单参数语法
可以省略前面的小括号
param1 -> {
statment1;
statment2;
//.............
return statmentM;
}
单语句语法
可以省略后面的大括号, 以及 return 语句。
param1 -> statment
方法引用语法
Class or instance :: method
变量作用域
外部变量在 lambda 表达式引用时,jdk 8 编译器会隐式做为 final 来处理
stream
上面的转换成小写就是一个 stream 的例子。
执行概况
生成
collection.stream()
转换
- distinct
- filter
- map
- flatMap
- peak
- limit
- skip
汇聚(Reduce)
collect 方法
示例
public class MainLambda {
public static void main(String[] args) {
List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
List<Integer> numsWithoutNull = nums.stream()
.filter(num -> num != null)
.collect(
() -> new ArrayList<Integer>(),
(list, item) -> list.add(item),
(list1, list2) -> list1.addAll(list2)
);
System.out.println(numsWithoutNull);
}
}
结果
[1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
其中 collect 有三个参数
- supplier: 生成一个新的实例
- accumulator(对象,元素): 把元素加入对象中
- combiner(对象, 对象): 合并两个对象
此外,JDK 提供了 Collector 接口,方便来写 collect。这里不多写了。
另外,JDK 预定义了常用的 Collector 接口实现,如 Collectors.toList()之类。
因此,上面的例子可以写成
public class MainLambda {
public static void main(String[] args) {
List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
List<Integer> numsWithoutNull = nums.stream()
.filter(num -> num != null)
.collect(Collectors.toList());
System.out.println(numsWithoutNull);
}
}
结果
[1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
reduce 方法
示例:求和元素
import com.google.common.collect.Lists;
public class MainLambda {
public static void main(String[] args) {
List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int value = ints.stream()
.reduce((sum, item) -> sum + item)
.get();
System.out.println("ints sum is:" + value);
}
}
结果
ints sum is:55
其中 reduce 的两个参数,第一个参数 sum 是上一次 reduce 的返回值,第二个参数是本次的元素。所以实际执行过程是: ( ( ( (1+2) + 3 ) + 4 ) + 5 )
也可以提供一个循环的初始值,如 -1
import java.util.List;
import com.google.common.collect.Lists;
public class MainLambda {
public static void main(String[] args) {
List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int value = ints.stream()
.reduce(-1, (sum, item) -> sum + item);
System.out.println("ints sum is:" + value);
}
}
结果
ints sum is:54
count
示例
import java.util.List;
import com.google.common.collect.Lists;
public class MainLambda {
public static void main(String[] args) {
List<Integer> ints = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long value = ints.stream().count();
System.out.println("ints sum is:" + value);
}
}
结果
ints sum is:10
其它
- allMatch: 均匹配
- anyMatch: 有一个匹配
- findFirst: 返回第一个元素,如果为空则返回 Optional
- noneMatch: 均不匹配
- max: 最大值
- min: 最小值
执行示例
import java.util.List;
import com.google.common.collect.Lists;
public class MainLambda {
public static void main(String[] args) {
List<Integer> nums = Lists.newArrayList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
int sum = nums.stream()
.filter(num -> num != null)
.distinct()
.mapToInt(num -> num * 2)
.skip(2)
.limit(4)
.peek(System.out::println)
.sum();
System.out.println("sum is:" + sum);
}
}
结果: 首先 skip 掉了前 2 个元素,又 limit 了 4 个元素,所以最后剩下了 6,8,10,12 共 4 个元素,其和为 36。
6
8
10
12
sum is:36
并行执行
通过 parallelStream
,来实现并行执行,默认为 8 个并发。
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Response;
public class Java8AsyncRequest {
public static void main(String[] args) {
List<String> emitters = new ArrayList<String>();
for (int i = 0; i != 1000; ++i) {
emitters.add("http://www.abeffect.com/" + i);
}
emitters.parallelStream().map(new Function<String, Response>() {
@Override
public Response apply(String s) {
try {
System.out.println(Thread.currentThread() + ": " + s);
Thread.sleep(5000L);
return Request.Get(s).execute();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
return null;
}
}
}).forEach(new Consumer<Response>() {
@Override
public void accept(Response response) {
try {
System.out.println(response.returnResponse().getStatusLine().getStatusCode());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于