Stream流
1.Stream流的介绍
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java集合运算和表达的高阶抽象。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream(流)是一个来自数据源的元素队列并支持聚合操作元素是特定类型的对象,形成一个队列。
Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组等。
聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
每次流使用完后,必须创建一个新的流去接受。不然会出现流已被使用或不存在的情况
2.创建Stream流
可以通过Conllection系列集合提供的顺序流stream()或并行流parallelStream()
List<String> list=new ArrayList<>(); Stream<String> stream = list.stream();
通过Arrays中的静态方法stream()获取数据流
Integer ints[] = new Integer[10]; Stream<Integer> stream2 = Arrays.stream(ints);
通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc"); String str[] = new String[10]; Stream<String> stream4 = Stream.of(str) ;
3.Stream流的中间操作
例:
static List<Employee> list= Arrays.asList( new Employee("小明",18), new Employee("小红",19), new Employee("邹辉",30), new Employee("小黑",20));
fliter
filter-接收Lambda,从流中排除某些元素
Stream<Employee> stream = list.stream(); Stream<Employee> employeeStream = stream.filter((e) -> { System.out.println("------过滤-----"); return e.getAge() >= 20;//筛选年龄大于等于20的元素 }); // 终止操作:一次性执行全部内容,即“惰性求值” employeeStream.forEach(System.out::println);
一般的遍历都是从上往下执行 会执行四次过滤 再输出元素
而流的运行顺序是流里面的元素先执行过滤,再看是否被过滤,不符合条件的则不被输出
一个元素直接完成方法后,再走下一个元素
limit
limit-截断流,使其元素不超过给定数量
Stream<Employee> stream = list.stream(); stream.filter((employee -> { return employee.getAge()>=18;//过滤年龄大于等于18的元素 })).limit(3)//-->限制元素个数为3 .forEach(System.out::println);
符合条件的元素有4个 但有limit限制 限制了过滤的元素个数 所以最多只能取3个元素。
skip
skip-跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流
Stream<Employee> stream = list.stream(); stream.filter((employee -> { return employee.getAge()>=18; })).skip(2)//-->丢掉前面两个元素 .forEach(System.out::println);
符合条件的元素有4个,但扔掉了前面两个元素,所以只剩两个元素了。
distinct
distinct-筛选,通过流所生产元素的hashCode()和equals()去除重复元素
使用distinct方法时,类中记得重写hascode()和equals()方法
Stream<Employee> stream = list.stream(); Stream<Employee> employeeStream = stream.filter((employee -> { return employee.getAge() > 18; })); employeeStream=employeeStream.filter((e)->{ return e.getName().equals("小黑"); }).distinct();//去重 employeeStream.forEach(System.out::println);
sorted(Comparable)-自然排序
List<String> list = Arrays.asList("cc", "aa", "bb", "ee", "dd"); list.stream().sorted().forEach(System.out::println);
sorted(Comparator)-定制排序
emps.stream().sorted((e1, e2) -> { if(e1.getAge().equals(e2.getAge())) { return e1.getName().compareTo(e1.getName()); }else { return e1.getAge().compareTo(e2.getAge()); } }).forEach(System.out::println);
map
map流中的每一个数据,当做map方法的参数(接口),接口中抽象方法的参数,进行制定操作,最终得到一个结果,最后所有的结果返回去成本为一个流。
相当于遍历,操作每一个 数据,得到多个结果组成一个新的流返回。
public static void testMap(){ list.stream() .map(e->e.getName()) .forEach(System.out::println); }
flatMap
流中的每一个数据当做参数,进行操作 ,得到的结果必须是一个流,最终会结合成一个流返回
Stream<String> s = Stream.of("aaa","bbb","ccc"); Stream<Character> haha= s.flatMap(StreamDemo03::testCharacter); //{a,a,a,b,b,b,c,c,c} haha.forEach(System.out::println);
4.Stream终止操作
allMatch-检查是否匹配所有元素
boolean b1 = emps.stream() .allMatch((e) -> e.getStatus().equals(Status.BUSY)); System.out.println(b1);
anyMatch-检查是否至少匹配一个元素
boolean b2 = emps.stream() .anyMatch((e) -> e.getStatus().equals(Status.BUSY)); System.out.println(b2);
noneMatch-检查是否没有匹配所有元素
boolean b3 = emps.stream() .noneMatch((e) -> e.getStatus().equals(Status.OTHER)); System.out.println(b3);
findFirst-返回第一个元素 如果第一个元素为空会报异常
// 需求:按工资排序,获取第一个员工信息
Optional<Employee> op1 = emps.stream() .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())) .findFirst(); System.out.println(op1.get());
可以使用orElse避免报异常
findAny-返回当前流中的任意元素
// 需求:找一个空闲状态的员工,添加到开发团队中
Optional<Employee> op2 = emps.parallelStream()// 并行流-多条线程进行,谁先找到就是谁 .filter((e) -> e.getStatus().equals(Status.FERR)) .findAny(); System.out.println(op2.get());
count-返回流中元素的总个数
Long count = emps.stream().count(); System.out.println(count);
max-返回流中最大值
Optional<Employee> op3 = emps.stream() .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())); System.out.println(op3.get());
min-返回流中最小值
Optional<Double> op4 = emps.stream() .map(Employee::getSalary) .min(Double::compare); System.out.println(op4.get());
5.Stream收集
收集-将流转换为其他形式,接收一个Collertor接口的实现,用于给Stream中元素做汇总的方法
// 需求:获取当前公司所有员工的姓名添加到集合中 // List-把流中所有元素收集到List中 List<String> list = emps.stream() .map(Employee::getName) .collect(Collectors.toList()); list.forEach(System.out::println); // Set-把流中所有元素收集到Set中,删除重复项 Set<String> set = emps.stream() .map(Employee::getName) .collect(Collectors.toSet()); set.forEach(System.out::println); // Map-把流中所有元素收集到Map中,当出现相同的key时会抛异常 Map<String, Integer> map = emps.stream() .collect(Collectors.toMap(Employee::getName, Employee::getAge)); System.out.println(map); // 员工总数 Long count = emps.stream().collect(Collectors.counting()); System.out.println(count); // 工资平均数 Double avg = emps.stream() .collect(Collectors.averagingDouble(Employee::getSalary)); System.out.println(avg); // 工资总和 Double sum = emps.stream() .collect(Collectors.summingDouble(Employee::getSalary)); System.out.println(sum); // 工资最大值的员工 Optional<Employee> op = emps.stream() .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))); System.out.println(op.get());