Stream流的应用
Stream 流:对数据进行操作
数据源:集合、数组
一系列流水线式中间操作
产生新的流,不改变原有流。
流是什么?
是数据渠道,用于操作数据源所生成的元素序列。
集合讲的是数据,流讲的是计算!
注意:
- Stream自己不会存储元素
- Stream不会改变原对象
- Stream操作是延时的
操作:
- 创建Stream
- 中间操作
- 终止操作(终端操作)
一、创建流的几种方式:
-
通过Collection系列集合提供的Stream()或parallelStream()
-
通过Arrays中的静态方法stream()获取数组流
-
通过Stream类中的静态方法of()
-
创建无限流
public class StreamAPITest01 {
//创建Stream
public static void main(String[] args){
//1、通过Collection系列集合提供的Stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Stream<String> stringStream = list.parallelStream();
//2.通过Arrays中的静态方法stream()获取数组流
Integer[] i1 = new Integer[10];
Stream<Integer> stream2 = Arrays.stream(i1);
//3.通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
//4创建无限流
//迭代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.limit(10)
.forEach(System.out::println);
//生成
Stream.generate(()->Math.random())
.limit(10)
.forEach(System.out::println);
}
}
二、流的中间操作
-
筛选与切片
- filter--接收Lambda,从流中排除默写元素
- limit--截断流,使其元素不超过给定数量
- skip(n)--跳过元素,扔掉前n个元素的流,数量不足返回空流
- distinct--筛选,通流所生成的hashCode()和equals()去除重复元素
public class StreamAPITest02 {
public static void main(String[] args) {
//中间操作
/*
筛选与切片
filter--接收Lambda,从流中排除默写元素
limit--截断流,使其元素不超过给定数量
skip(n)--跳过元素,扔掉前n个元素的流,数量不足返回空流
distinct--筛选,通流所生成的hashCode()和equals()去除重复元素
*/
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99),
new Employee("李四", 58, 5555),
new Employee("王五", 26, 333.33),
new Employee("赵六", 36, 666.66),
new Employee("田七", 12, 888.88)
);
//filter的使用
//内部迭代 迭代由Streamle API完成
Stream<Employee> stream = employees.stream()
.filter((e) -> {
System.out.println("Stream API 的中间操作!");
return e.age > 35;
});
//在执行 以下终止操作后才会一次性全部处理,称为“惰性求值”
stream.forEach(System.out::println);
//外部迭代
Iterator<Employee> it = employees.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//limit的使用
employees.stream()
.filter((e) -> e.getMoney() > 5000)
.limit(2)
.forEach(System.out::println);
//skip和distinct的使用
employees.stream()
.filter((e) -> e.getMoney() > 5000)
.skip(2)
.distinct()
.forEach(System.out::println);
}
}
2.映射
- map--接收Lambda,将元素转换成其他形式或提取信息
- flatMap--接收一个函数作为参数,将流中每个值换成另一个流,然后把所有流连接成一个流
public class StreamAPITest03 {
public static void main(String[] args) {
/*
映射
map--接收Lambda,将元素转换成其他形式或提取信息
flatMap--接收一个函数作为参数,将流中每个值换成另一个流,然后把所有流连接成一个流
*/
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99),
new Employee("李四", 58, 5555),
new Employee("王五", 26, 333.33),
new Employee("赵六", 36, 666.66),
new Employee("田七", 12, 888.88)
);
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
//map的使用
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
System.out.println("----------------------------");
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
Stream<Stream<Character>> streamStream = list.stream()
.map(StreamAPITest03::filterCharacter);
//流形式为:{{a,a,a},{b,b,b}}
streamStream.forEach(stm -> {
stm.forEach(System.out::println);
});
//flatMap的使用
System.out.println("-----------------------------");
Stream<Character> characterStream = list.stream()
.flatMap(StreamAPITest03::filterCharacter);
//流形式为:{a,a,a,b,b,b}
characterStream.forEach(System.out::println);
System.out.println("-------------------------------");
}
public static Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch:str.toCharArray()){
list.add(ch);
}
return list.stream();
}
}
3.排序
- sorted()--自然排序)(Comparable)
- sorted(Comparator)--定制排序
public class StreamAPITest04 {
public static void main(String[] args){
/*
sorted()--自然排序)(Comparable)
sorted(Comparator)--定制排序
*/
List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("------------------------------");
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99),
new Employee("李四", 58, 5555),
new Employee("王五", 26, 333.33),
new Employee("赵六", 36, 666.66),
new Employee("田七", 12, 888.88)
);
employees.stream()
.sorted((e1,e2)->{
if (e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
}else {
return e1.getAge()-e2.getAge();
}
})
.forEach(System.out::println);
}
}
4. 查找与匹配
- allMatch--检查匹配所有 元素
- anyMatch--检查是否至少匹配一个元素
- noneMatch--检查是否没有匹配所有元素
- findFirst--返回第一个元素
- findAny -- 返回当前流中任意元素
- count--返回流中元素个数
- max--返回流中最大值
- min--返回流中最小值
public class StreamAPITest05 {
public static void main(String[] args){
/*
查找与匹配
allMatch--检查匹配所有 元素
anyMatch--检查是否至少匹配一个元素
noneMatch--检查是否没有匹配所有元素
findFirst--返回第一个元素
findAny -- 返回当前流中任意元素
count--返回流中元素个数
max--返回流中最大值
min--返回流中最小值
*/
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
new Employee("李四", 58, 5555, Employee.Status.FTEE),
new Employee("王五", 26, 333.33, Employee.Status.BUSY),
new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
);
//是否匹配所有元素
boolean b1 = employees.stream()
.allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
//至少匹配一个
boolean b2 = employees.stream()
.anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b2);
//没有匹配所有元素 有匹配的元素
boolean b3 = employees.stream()
.noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b3);
//返回第一个
Optional<Employee> op = employees.stream() //提供op.orElse(other),如果对象为空则用other代替,避免空指针
.sorted((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()))
.findFirst();//值有可能为空 封装到Optional中
System.out.println(op.get());
//返回任意一个
Optional<Employee> any = employees.stream()
.filter(e -> e.getStatus().equals(Employee.Status.FTEE))
.findAny();
System.out.println(any.get());
//个数
long count = employees.stream()
.count();
System.out.println(count);
//最大值
Optional<Employee> max = employees.stream()
.max((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()));
System.out.println(max.get());
//最小值
Optional<Employee> min = employees.stream()
.min((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()));
System.out.println(min.get());
}
}
三、流的终止操作
1.归约与收集
-
归约:reduce(T identity,BinaryOperator) reduce(BinaryOperator)
--可以将流中元素反复结合起来得到一个值
-
收集collect
--将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
public class StreamAPITest06 {
public static void main(String[] args) {
//归约:reduce(T identity,BinaryOperator)/deduce(BinaryOperator
//--可以将流中元素反复结合起来得到一个值
List<Integer> list = Arrays.asList(1,2,4,5,6,7,8);
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(sum);
System.out.println("------------------------------------------");
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
new Employee("李四", 58, 5555, Employee.Status.FTEE),
new Employee("王五", 26, 333.33, Employee.Status.BUSY),
new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
);
//可能为空返回Optional
Optional<Double> op = employees.stream()
.map(Employee::getMoney)
.reduce(Double::sum);
System.out.println(op.get());
//收集
//collect--将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
employees.stream()
.map(Employee::getName)
.collect(Collectors.toList())
.forEach(System.out::println);
System.out.println("--------------------------------------------");
Set<String> set = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
System.out.println("-----------------------------------------------");
HashSet<String> hashSet = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
System.out.println("------------------------------------------------");
//总数
Long count = employees.stream()
.collect(Collectors.counting());
System.out.println(count);
System.out.println("-------------------------------------");
//平均值
Double avg = employees.stream()
.collect(Collectors.averagingDouble(Employee::getMoney));
System.out.println(avg);
System.out.println("-------------------------------------");
//工资总和
Double sum1 = employees.stream()
.collect(Collectors.summingDouble(Employee::getMoney));
System.out.println(sum1);
System.out.println("-------------------------------------");
//最大值
Optional<Employee> max = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getMoney(), e2.getMoney())));
System.out.println(max.get());
System.out.println("-------------------------------------");
//最小值
Optional<Double> min = employees.stream()
.map(Employee::getMoney)
.collect(Collectors.minBy(Double::compare));
System.out.println(min);
}
}
- 收集的应用--分组/多级分组
public class StreamAPITest07 {
public static void main(String[] args) {
//分组
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
new Employee("李四", 58, 5555, Employee.Status.FTEE),
new Employee("王五", 26, 333.33, Employee.Status.BUSY),
new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
);
//
Map<Employee.Status, List<Employee>> map = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(map);
//多级分组
Map<Employee.Status, Map<String, List<Employee>>> map1 = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> {
if (((Employee) e).getAge() <= 35) {
return "青年";
} else if (e.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
System.out.println(map1);
}
}
- 收集的应用--分区
public class StreamAPITest08 {
public static void main(String[] args) {
//分区
List<Employee> employees = Arrays.asList(
new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
new Employee("李四", 58, 5555, Employee.Status.FTEE),
new Employee("王五", 26, 333.33, Employee.Status.BUSY),
new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
);
Map<Boolean, List<Employee>> map1 = employees.stream()
.collect(Collectors.partitioningBy((e) -> e.getMoney() > 8000));
System.out.println(map1);
DoubleSummaryStatistics dss = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getMoney));
System.out.println(dss.getAverage());
System.out.println(dss.getCount());
System.out.println(dss.getMax());
System.out.println(dss.getMin());
System.out.println(dss.getSum());
String str = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",","===","==="));
System.out.println(str);
}
}