一、Stream 的三个操作
1、创建Stream 流
// 1.可以通过Collection 系列集合提供的Stream()-串行流 或 parallelStream()-并行流 获取流
List<String> list = new ArrayList<>();
Stream<String> stringStream = list.stream();
// 2.可以通过Arrays中的静态方法stream() 获取流
Employee[] employees = new Employee[10];
Stream<Employee> employeeStream = Arrays.stream(employees);
// 3.通过Stream类中的静态方法of()获取流
Stream<String> stream = Stream.of("aa","bb","cc");
// 4.创建无限流
// 4.1 迭代
Stream<Integer> integerStream = Stream.iterate(0,x -> x++);
integerStream
.limit(20)
.forEach(System.out::println);
// 4.2 生成
Stream.generate(()-> Math.random())
.limit(10)
.forEach(System.out::println);
2、中间操作 :不会执行任何操作。
2.1、筛选与切片
filter---接受Lambda,从流中排除某些元素。//需要一个断言型接口
limit(n)---截断流,使其元素不超过给定的数量。
skip(n)---跳过元素,返回一个扔掉前n个元素的流。若流中元素不足n个,则返回一个空的流。与limit(n)互补。
distinct---筛选,通过流生成的元素的hashCode()和equals() 去除重复的元素。
注意:多个中间操作可以连接起来形成一个流水线,除非流水线上出发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为‘’惰性求值‘’。
2.2、映射
map---接受Lambda ,将元素转为其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap---接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流。
2.3、排序
sorted()---自然排序(Comparable)
sorted(Comparator com)---定制排序(Comparator)
-
内部迭代:迭代由StreamAPI完成
employeeList.stream() .filter(e -> e.getAge()>20) .forEach(System.out::println);
-
外部迭代 : 需要自己写迭代器完成
Iterator<Employee> it = employeeList.iterator(); while (it.hasNext()){ System.out.println(it.hasNext()); }
3、终止操作(终端操作):一次性执行全部内容。
3.1、查找与匹配
allMatch---检查是否匹配所有元素
anyMatch---检查是否至少匹配一个元素
noneMAtche---检查是否匹配所有元素
findFirst---返回第一个元素
count---返回流中元素的个数
max---返回流中最大值
min---返回流中元素最小值
3.1、归约
reduce(T indentiy,BinaryOperator)/reduce(BinaryOperator)---可以将流中元素反复集合起来,得到一个值。
解释:以起始值(自己定义的值)开始,按照自定义的函数式反复归约(计算)得出一个结果。
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
// 需求 计算集合中数据的总和
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);//第一个参数为起始值,第二个参数是一个自定义的运算函数式(根据自己的需求)
System.out.println(sum);
——------------------------------------------------------------------------------------------------------------------
List<Employee> employeeList = Arrays.asList(
new Employee("张无忌",24,5500.00),
new Employee("李茂贞",33,6500.00),
new Employee("杨过",28,5900.00),
new Employee("武庚",28,8400.00),
new Employee("叶星云",35,9000.00),
new Employee("叶辰",20,7400.00),
new Employee("姬如雪",25,5600.00));
// 需求 :计算员工工资总和
Optional<Double> reduce = employeeList.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(reduce.get());
备注:map-reduce 通常被称为map-reduce模式,Google用它来进行网络搜索而出名。
3.2、收集
collect---将流转换为其他形式。接受一个Collector接口的实现,用于给Stream中元素做汇总的方法。
// 将员工姓名提成一个集合
employeeList.stream()
.map(Employee::getName)
.collect(Collectors.toList())
.forEach(System.out::println);
/**要提取成其他形式例如HashSet**/
employeeList.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new))// 用toCollection方法
.forEach(System.out::println);
4、并行流与顺序流
fork/join
/**
* @Author: Kra
* @Version: 1.0
* @Date: 2022/02/28/ 16:00
* @Description:
*/
public class ForkJoinCalculate extends RecursiveTask<Long> {
private long start;
private long end;
private static final long THRESHOLD = 10000;
public ForkJoinCalculate(long start, long end) {
this.start = start;
this.end = end;
}
/**
* The main computation performed by this task.
*
* @return the result of the computation
*/
@Override
protected Long compute() {
long length = end - start ;
if(length <= THRESHOLD){
long sum = 0;
for (long i = start; i < end; i++) {
sum += i;
}
return sum;
}else {
long middle = (start + end) / 2;
// 拆分子任务,压入线程队列
ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
left.fork();
ForkJoinCalculate right = new ForkJoinCalculate(middle + 1, end);
right.fork();
// 合并子任务并返回
return left.join()+right.join();
}
}
}
/**
* @Author: Kra
* @Version: 1.0
* @Date: 2022/02/28/ 16:44
* @Description:
*/
public class TestForkJoin {
@Test
public void test(){
Instant startTime = Instant.now();
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Long> forkJoinTask = new ForkJoinCalculate(0,10000000000l);
Long sum = pool.invoke(forkJoinTask);
System.out.println(sum);
Instant endTime = Instant.now();
System.out.println("耗费时间为:"+Duration.between(startTime, endTime).toMillis());//756
}
//消耗时间对比:
@Test
public void test2(){
Instant startTime = Instant.now();
long sum = 0;
for (long i = 0; i <10000000000l ; i++) {
sum+=i;
}
Instant endTime = Instant.now();
System.out.println("耗费时间为:"+Duration.between(startTime, endTime).toMillis());// 2235
}
}
5、Optional类
Optional类,是一个容器类,代表一个值存在或不存在,原来是用null表示不存在,现在Optional可以更好的表达这个概念,并且避免空指针异常。
常用方法:
Optional.of(T t)---创建一个Optional实例。
Optional.empty()---创建一个空的Optional实例。
Optional.ofNullable(T t)---若t不为null,创建实例Optional,否则创建空实例。
isPresent()---判断是否包含值。
orElse(T t)---如果调用对象包含值,则返回该值,否则返回t。
orElseGet(Supplier s)---如果调用对象包含值,返回该值,否则返回t。
map(Function f)---如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()。
flatMap(Function mapper)---与map类似,要求返回值必须是Optional。