lambda表达式Stream流学习十—Stream操作练习题,map、sorted、collect、filter、forEach、max、min
一,Optional
Optional类(java.util.Optional)是一个容器,代表一个值存在或者不存在,原来用 null 来表示一个值不存在,现在Optional可以更好的表达这个概念,并且可以避免空指针异常。
/*
Optional 常用方法 :
Optional.of(T t) : 创建一个 Optional 实例
Optional.empty() : 创建一个空的 Optional 实例
Optional.ofNullable(T t) : 若t不为null,创建Optional实例,否则创建空实例
Optional.isPresent() : 判断是否包含值
orElse(T t) : 如果对象包含值,则返回该值,否则返回t
orElseGet(Supplier s) : 如果对象包含值,返回该值,若不包含,返回s获取的值
map(Function f) : 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
faltMap(Function mapper) : 与map类似,要求返回值必须是Optional
*/
public class OptionalClass {
@Test
public void test1(){
Optional<Employee> op = Optional.of(new Employee());//注意of里面的值不能为null
Employee e = op.get();
System.out.println(e);
}
@Test
public void test2(){
Optional<Employee> op = Optional.empty();//创建一个空的Optional实例
System.out.println(op.get());//空Optional不能get,会报错
}
@Test
public void test3(){
Optional<Employee> op = Optional.ofNullable(new Employee());//若T不为null则相当于test1,若为null,则相当于test2
if (op.isPresent()){//判断是否为不为空, return value != null;
System.out.println(op.get());
}
}
@Test
public void test4(){
Optional<Employee> op = Optional.ofNullable(null);//T为空,则创建一个空的Optional实例
Employee emp = op.orElse(new Employee("lala", 21, 10000, Employee.status.VOCATION));
//orelse,如果调用的对象有值则返回包含的值,否则返回括号的值
System.out.println(emp);
Employee emp2 = op.orElseGet(() -> new Employee());//supplier函数,可以在内部做逻辑处理
System.out.println(emp2);
}
@Test
public void test5(){
Optional<Employee> op = Optional.ofNullable(new Employee("lala", 21, 10000, Employee.status.VOCATION));
Optional<String> op2 = op.map(e -> e.getName());//如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
System.out.println(op2.get());
Optional<String> op3 = op.flatMap(e -> Optional.ofNullable(e.getName()));//与map类似,要求返回值必须是Optional
System.out.println(op3.get());
}
}
二,ForkJoin 框架
ForkJoin 框架 : 就是在必要的情况下,将一个大任务进行拆分(fork)成若干个小任务(拆到不可再拆分为止),然后再将一个个的小任务的运算结果进行join汇总。
//案例 :
public class ForkJoin extends RecursiveTask<Long> {
private long start;
private long end;
private static final long THRESHOLD = 100000000L;
public ForkJoin(long start, long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
long len = end - start;
if (len <= THRESHOLD){
long sum = 0;
for (long l=0; l<=end; l++){
sum += l;
}
return sum;
}else {
long middle = (start + end)/2;
ForkJoin leftFork = new ForkJoin(start, middle);//拆分子任务,同事压入线程池
ForkJoin rightFork = new ForkJoin(middle+1, end);
leftFork.fork();
rightFork.fork();
return leftFork.join() + rightFork.join();
}
}
}
//使用ForkJoin框架,在数据量特别大时比较明显
@Test
public void test1(){
Instant start = Instant.now();//Instance与Duration都是Java1.8新增的时间工具类,java.time包下
ForkJoinPool forkJoinPool = new ForkJoinPool();//使用ForkJoin需要ForkJoin线程池
ForkJoinTask<Long> forkJoinTask = new ForkJoin(0, 100000000L);
Long sum = forkJoinPool.invoke(forkJoinTask);
System.out.println(sum);
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
@Test
public void test2(){
Instant start = Instant.now();
long sum = 0;
for (long l=0; l<100000000L; l++){
sum += l;
}
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());
}
三,并行流与顺序流
并行流与顺序流:并行流就是把一个内容分为多个数据块,并且用不同的线程分别处理每个数据块的流。
Java8 中将并行流进行了优化,我们可以很容易的对数据进行并行操作,Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流直接进行切换。
@Test
public void test3(){
Instant start = Instant.now();
LongStream.rangeClosed(0, 1000000000L)
.parallel().reduce(0, Long::sum);//parallel() 声明为并行流,极大提升效率,底层运用了ForkJoin
Instant end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());//174
start = Instant.now();
LongStream.rangeClosed(0, 1000000000L)
/*.sequential()*/.reduce(0, Long::sum);
end = Instant.now();
System.out.println(Duration.between(start, end).toMillis());//1983
}
本文详细介绍了Java 8中的Optional类及其常用方法,如of、empty、isPresent、orElse等,并通过示例展示了如何使用map和flatMap。接着,深入讲解了ForkJoin框架的工作原理,通过递归任务实现大任务的拆分和结果汇总。最后,对比了并行流和顺序流在处理大数据时的效率差异,演示了parallel()和sequential()的使用。
15

被折叠的 条评论
为什么被折叠?



