java 8 新特性(二) stream API
java 8 新特性(二) stream API
stram的三个操作 :
- 创建stram
- 中间操作
- 终止操作(终端操作)
一、创建stream的几种方式:
// 第一种: 可以通过Collection 系列集合提供的 stream() 或 parallelStream()
Map<String,Object> map = new HashMap<>();
employees.stream(); // 串行流
employees.parallelStream(); // 并行流
System.out.println("--------------------------------------------------------------");
// 第二种. 通过 Arrays 中静态方法 stream() 获取数组流
Integer[] array = new Integer[10];
Stream<Integer> stream = Arrays.stream(array);
System.out.println("--------------------------------------------------------------");
// 第三种: 通过stream() 类中的静态方法 of()
Stream<String> stream3 = Stream.of("aa","bb","cc");
// 第四种: 创建无限流(无穷尽) 迭代
/**
* iterate:
* 该方法实现了 函数式接口
* @FunctionalInterface
* public interface UnaryOperator<T> extends Function<T, T> {}
*
* 三个步骤的体现:(基本上stream的操作都会存在该三步)
* Stream.iterate(9,x->x+2).limit(10).forEach(System.out::println);
* Stream.iterate(9,x->x+2) : 开始
* .limit(10): 中间操作
* .forEach(System.out::println): 终止操作
*/
// Stream.iterate(9,x->x+2).forEach(System.out::println);
Stream.iterate(9,x->x+2).limit(10).forEach(System.out::println);
结果:
--------------------------------------------------------------
--------------------------------------------------------------
9
11
13
15
17
19
21
23
25
27
二、stream 的中间操作的方法API:
测试数据:
public static List<Employee> employees = Arrays.asList(
new Employee("张三",18,1111.00),
new Employee("李四",28,2222.00),
new Employee("王五",38,3333.00),
new Employee("赵六",48,4444.00),
new Employee("候七",58,5555.00)
);
(筛选与切片)
-
filter 在流中排除某些元素
-
distinct 筛选 通过 hashCode 与 equals 去重
-
limit 截断 使元素不超过给定的数量
System.out.println("--------------------------------------------------------------");
// 中间操作 filter 中间操作后面必须要有终止操作,若没有终止操作 中间操作的流没有任何结果的
employees.stream().filter(x -> x.getAge() >35).forEach(System.out::println);
System.out.println("--------------------------------------------------------------");
/**
* 惰性求值:
* 就是多个中间操作可以连接起来行成一个流水线,除非流水线上触发了终止操作,
* 否则中间操作不会执行任务的处理,而在终止操作时一次性全部执行
* 内部迭代: 迭代操作时有stream api完成
* 外部迭代: 自己通过迭代语句执行
*/
结果:
--------------------------------------------------------------
Employee{name='王五', age=38, salary=3333.0}
Employee{name='赵六', age=48, salary=4444.0}
Employee{name='候七', age=58, salary=5555.0}
--------------------------------------------------------------
- skip 跳过元素 返回一个扔掉了钱n个元素的流 若流中元素不足n个, 则返回一个空流 与limit() 互补
// .skip(2) 跳过两条数据 取第三条数据
employees.stream().filter(x->x.getAge()>35).skip(2).forEach(System.out::println);
结果:
Employee{name='候七', age=58, salary=5555.0}
(映射)
- map 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个元素
List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
strings.stream().map(str->str.toUpperCase()).forEach(System.out::println);
结果:
AA
BB
CC
DD
采用语法糖的方式:
// 类名::方法名 这是java的语法糖
strings.stream().map(StramAPI01::filterCharacter)
.forEach(x->x.forEach(System.out::println));
private static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch: str.toCharArray()){
list.add(ch);
}
return list.stream();
}
结果:
a
a
b
b
c
c
d
d
-
mpaToDouble 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个DoubleStream
-
mapTOInt 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个intStream
-
mapToLong 接收一个函数为参数 该函数会被应用到每个元素上,并将其映射成新的一个longStream
-
flatMap 接收一个函数为参数 将流中的每个值都换成另一流 然后把所有的流连成一个流程
以上采用 采用语法糖的方式 的简化 采用 flatMap 可以实现
strings.stream().flatMap(StramAPI01::filterCharacter).forEach(System.out::println);
结果:
a
a
b
b
c
c
d
d
flatMap 与 map的区别
举例说明:
有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。
map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;
flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生;
(排序)
-
sorted() 产生一个新流 其中按自然顺序排序
-
sorted(Comparator comp) 产生一个新流 其中按比较器顺序排序
List<String> strings = Arrays.asList("ee","aa", "bb", "cc", "dd");
strings.stream().sorted().forEach(System.out::println);
结果:
aa
bb
cc
dd
ee
-- 带参数的排序 按照年龄来排序
employees.stream().sorted((x1,x2)-> x1.getAge().compareTo(x2.getAge())).forEach(System.out::println);
结果:
Employee{name='张三', age=18, salary=1111.0}
Employee{name='李四', age=28, salary=2222.0}
Employee{name='李四1', age=29, salary=2233.0}
Employee{name='王五', age=38, salary=3333.0}
Employee{name='赵六', age=48, salary=4444.0}
Employee{name='候七', age=58, salary=5555.0}
三 、stream 的终止操作的方法API:
(查找与匹配)
- allMath 检查是否匹配所有元素
boolean b1 = empLists.stream().allMatch(x->x.getAge().equals(18));
System.out.println("b1=="+ b1);
结果:
b1==false
- anyMath 检查是否至少匹配一个元素
boolean b2 = empLists.stream().anyMath(x->x.getAge().equals(18));
System.out.println("b2=="+ b2);
结果:
b2==true
- noneMath 检查是否有匹配的所有与元素
boolean b3 = empLists.stream().noneMath(x->x.getAge().equals(18));
System.out.println("noneMath b3=="+ b3);
结果:
noneMath b3==false
- findFirst 返回第一个元素
Optional<Employee> em1 = empLists.stream().findFirst();
System.out.println("findFirst em1=="+ em1);
结果:
findFirst em1==Optional[Employee{name='张三', age=18, salary=1111.0}]
- findAny 返回当前流中的任意元素
Optional<Employee> o1 = empLists.stream().findAny();
System.out.println("findAny 01=="+ o1);
结果:
findAny 01==Optional[Employee{name='张三', age=18, salary=1111.0}]
- count
long count = empLists.stream().count();
System.out.println("count == "+ count);
结果:
count == 6
- max min
Optional<Employee> max = empLists.stream()
.max((x1,x2)->Integer.compare(x1.getAge(),x2.getAge()));
System.out.println("max==="+ max);
Optional<Employee> min = empLists.stream()
.min((x1,x2)->Integer.compare(x1.getAge(),x2.getAge()));
System.out.println("min==="+ min);
结果:
max===Optional[Employee{name='候七', age=58, salary=5555.0}]
min===Optional[Employee{name='张三', age=18, salary=1111.0}]
四、归约与收集 reduce 与 collect
- reduce
System.out.println("--------------------------------------------------------------");
List<Integer> list = Arrays.asList(1, 2, 4, 5, 6, 7, 3, 56, 10);
Integer sum = list.stream().reduce(0,(x,y)->x+y); // sum==94
System.out.println("sum=="+ sum);
System.out.println("--------------------------------------------------------------");
Integer sum1 = list.stream().reduce(1,(x,y)->x+y); // sum==95
System.out.println("sum1=="+ sum1);
System.out.println("--------------------------------------------------------------");
// 计算员工的工资总和
Optional<Double> sum2 = employees.stream().map(Employee::getSalary)
.reduce(Double::sum); // sum2===18898.0
System.out.println("sum2==="+ sum2.get());
备注:map 和 reduce 的连接通常称为 map-reduce 模式 ,因 Google 用它来进行网络搜索而出名。
- collect
// collect 收集器
// 案例1: 收集集合中的名字
List<String> nameList1 = employees.stream()
.map(Employee::getName) // 取出Employee中的员工名字
// Collectors : 计算集合的工具类
.collect(Collectors.toList());
System.out.println("nameList1 == "+ nameList1);
// nameList1 == [张三, 李四, 王五, 李四1, 赵六, 候七]
// 案例2:获取员工工资的平均值
Double d = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println("d ===="+ d); // d ====3149.6666666666665
//案例3: 分组 将集合List<Map>转换成map<key,List<Map>>类型
Map<Employee.Status,List<Employee>> map =
empLists.stream().collect(Collectors.groupingBy(Employee::getStatus));
System.out.println("map =="+ map);
// map =={
// VOCATION=[Employee{name='李四', age=28, salary=2222.0},
// Employee{name='候七', age=58, salary=5555.0}],
// BUSY=[Employee{name='张三', age=18, salary=1111.0}, Employee{name='李四1', age=29, salary=2233.0}],
// FREE=[Employee{name='王五', age=38, salary=3333.0}, Employee{name='赵六', age=48, salary=4444.0}]}
// Map<String,Map<String,List<Employee>> 类型
Map<Employee.Status, Map<String, List<Employee>>> map1 = empLists.stream()
.collect((
Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(
e -> {
if (((Employee) e).getAge() <= 35) {
return "青年";
} else if (((Employee) e).getAge() <= 50) {
return "中年";
} else {
return "老年";
}
}
))
));
// 结果:
map1 == {VOCATION={青年=[Employee{name='李四', age=28, salary=2222.0}], 老年=[Employee{name='候七', age=58, salary=5555.0}]}, BUSY={青年=[Employee{name='张三', age=18, salary=1111.0}, Employee{name='李四1', age=29, salary=2233.0}]}, FREE={中年=[Employee{name='王五', age=38, salary=3333.0}, Employee{name='赵六', age=48, salary=4444.0}]}}
五、并行流 与 串行流
Optional
Optional 容器类的常用方法
- Optional .of(T t) 创建一个一个Optional
- Optional.empty() 创建一个空的Optional 实例
- Optional.ofNullable(T t) 若t为null 创建Optional实例,否则创建空实例
- Optional.isPresent() 判断是否包含值
- Optional.orElse(T t) 如果调用对象包含值,返回该值,否则返回t
- Optional.orElseGet(Supplier s) 如果调用对象包含值,返回改值,否则返回s 获取的值
- Optional.,map(Function f) 如果值对其处理,并返回处理后的Optional 否则返回Optional.empty()
- Optional.flatMap(Function mapper) 与map类似,要求返回值必须是Optional