Stream是数据渠道,用于操作数据源(集合.数组等)所产生的元素序列. 集合讲的是数据,流看中计算!!
一个数据源(集合,数组),获取一个Stream流,获取Stream流的方式有四种:
//1.collection 系列集合提供的stream() 或者parallelStream()
ArrayList<String> strings = new ArrayList<>();
Stream<String> stream = strings.stream();
List<Employee> employees = Arrays.asList(
new Employee(1,"张三",13,12000.0),
new Employee(2,"李四",88,4200.0),
new Employee(3,"王五",23,3200.0),
new Employee(4,"赵六",5,1500.0),
new Employee(5,"田七",55,888.0),
new Employee(6,"古八",8,3000.0),
new Employee(6,"古八",8,3000.0)
);
//2.通过Arrays 中的静态方法 stream()获取数组流
Employee[] employees = new Employee[10];
Stream<Employee> employeeStream = Arrays.stream(employees);
//3.通过 Stream 类中的静态方法 of()
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4);
//4.1 迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 1);
iterate.limit(4).forEach(System.out::println);
//4.2 生成
Stream<Double> generate = Stream.generate(() -> Math.random());
generate.limit(5).forEach(System.out::println);
一个中间操作链,对数据源的数据进行处理
中间操作分为以下几类:
//filter 过滤
employees.stream()
.filter((x) -> x.getAge() > 10) //filter 中的参数是predicate接口类型,即 ==> boolean test(T t);
.forEach(System.out::println); //forEach 中的参数是consumer类型的,即 ==> void accept(T t);
//limit 限制
employees.stream()
.filter(x -> x.getSalary() > 2000) //filter 过滤
.limit(3) //限制3条记录
.forEach(x -> System.out.println("limit结果:" + x));
//skip(n) 跳过
employees.stream()
.skip(3) //跳过前三个
.filter(x -> x.getSalary() > 1000.0) //过滤
.forEach(x -> System.out.println("skip结果:" + x));
//distinct 去重
employees.stream()
.filter(x -> x.getId() > 2)
.distinct() //去重比较的是hashcode方法和equals方法
.forEach(x -> System.out.println("distinct:" + x));
//demo1 将集合中的元素,全部转为大写
List<String> strings = Arrays.asList("a", "b", "c", "d", "E");
strings.stream()
.map(str -> str.toUpperCase()) //接收一个Function参数 ==> R apply(T t);
.forEach(System.out::println);
System.out.println("============================");
//demo2
employees.stream()
.map(e -> e.getName()) //将每一个employee元素转换成employee中的name
.forEach(System.out::println);
System.out.println("============================");
//demo1 自然排序
List<String> strings = Arrays.asList("a", "d", "e", "c", "b");
strings.stream()
.sorted()
.forEach(System.out::println);
//demo2 定制排序
employees.stream()
.sorted((e1,e2) -> {
if(e1.getAge() == e2.getAge()){
return e1.getName().compareTo(e2.getName());
}else {
return Integer.compare(e1.getAge(),e2.getAge());
}
}).forEach(System.out::println);
1.匹配 (返回的boolean)
//allMatch 是否年龄都大于10岁
boolean allMatch = employees.stream()
.allMatch(e -> e.getAge() > 10);
System.out.println("所有的员工是否年龄都大于10岁:" + allMatch);
//anyMatch 查找是否有一个人的名字叫古八的
boolean anyMatch = employees.stream()
.anyMatch(e -> e.getName().equals("古八")); //查找是否有一个人的名字叫古八的
System.out.println("查找是否有一个人的名字叫古八:" + anyMatch);
//noneMatch 判断是不是没有人的工资高于20000
boolean noneMatch = employees.stream()
.noneMatch(e -> e.getSalary() > 20000); //判断是不是没有人的工资高于20000
System.out.println("判断是不是没有人的工资高于20000:" + noneMatch);
2.查找
//findFirst 获取年龄最小的员工
//optional优点类似于如果当前元素为空,则用null代替
Optional<Employee> first = employees.stream()
.sorted((e1, e2) -> {
if (e1.getAge() == e2.getAge()) {
return e1.getName().compareTo(e2.getName());
} else {
return Integer.compare(e1.getAge(), e2.getAge());
}
}).findFirst();
System.out.println("年龄最小的员工是:" + first);
System.out.println("================");
//count计数
long count = employees.stream()
.filter(e -> e.getSalary() > 3000)
.count();
System.out.println("工资大于3000的员工的数量:" + count);
System.out.println("=====================");
//max 年龄最大的员工的年龄是
Optional<Integer> maxAge = employees.stream()
.map(e -> e.getAge())
.max((e1, e2) -> Integer.compare(e1, e2));
System.out.println("员工中年龄最大为:" + maxAge);
3.规约(可以做统计)
List<Integer> list = Arrays.asList(1, 2, 4, 5, 6, 7, 8);
Integer reduce = list.stream()
//参数1 : 表示x的起始值,以后x的值等于x和集合中的每个元素计算得来的值;
//参数2 : 表示每一个流中的元素
.reduce(2, (x, y) -> x + y);
System.out.println(reduce);
System.out.println("====================");
Optional<Double> reduce1 = employees.stream()
.map(Employee::getSalary) //将流中的employee元素映射为工资元素
.reduce(Double::sum); //并且对工资求和
System.out.println(reduce1);
4.收集
//demo1 将所有的employee的员工姓名收集到一个集合中去
List<String> list = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());//去重复收集,因为是收集到set集合中去
list.forEach(System.out::println);
System.out.println("=========================");
//demo2 将所有的employee的员工姓名收集到一个集合中去
Set<String> set = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());//收集到list集合中去
set.forEach(System.out::println);
System.out.println("=========================");
//demo3 将所有的employee的员工姓名收集到一个集合中去
HashSet<String> hashSet = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));//收集到Hashset集合中去
hashSet.forEach(System.out::println);
//count 统计
Long count = employees.stream()
.collect(Collectors.counting());
System.out.println("员工总数:" + count);
//工资平均值
Double ave = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println("工资平均数:" + ave);
System.out.println("====================");
//工资总和
DoubleSummaryStatistics sum = employees.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println("工资总和:" + sum.getSum());
System.out.println("工资平均数:" + sum.getAverage());
System.out.println("统计数目:" + sum.getCount());
System.out.println("工资最高的:" + sum.getMax());
System.out.println("工资最低的:" + sum.getMin());
System.out.println("====================");
//工资最大值
Optional<Double> max = employees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1, e2)));
System.out.println("工资最高:" + max);
//年龄最小值
Optional<Integer> min = employees.stream()
.map(Employee::getAge)
.collect(Collectors.minBy((e1, e2) -> Integer.compare(e1, e2)));
System.out.println("年龄最小的为多少岁:" + min);
Map<String, List<Employee>> map = employees.stream()
.collect(Collectors.groupingBy((e) -> {
//分组,按照年龄分组;小于30的为青少年;30-60的为中年;60以上为老年
if (((Employee) e).getAge() < 30) {
return "青少年";
} else if (((Employee) e).getAge() < 60) {
return "中年";
} else {
return "老年";
}
}));
for (String s : map.keySet()) {
List<Employee> employees = map.get(s);
System.out.println(s + ":" + employees);
}
Map<Boolean, List<Employee>> map = employees.stream()
.collect(Collectors.partitioningBy((x) -> x.getSalary() > 3000)); //分区,工资大于3000的是一个区,工资小于等于3000的是一个区
for (Boolean aBoolean : map.keySet()) {
System.out.println(aBoolean + ":" + map.get(aBoolean));
}