Stream的作用
stream是java8中处理集合的关键抽象信息,它可以指定希望对集合进行的操作,可以执行查找、过滤和映射数据等操作。
使用StreamApi对集合数据进行操作,就类似于使用使用sql对数据库操作。简而言之,StreamApi提供了高效且易于使用的数据处理方式。
什么是流?
流指的是用于操作数据源所生成的元素序列。
需要注意的是:
(1)stream不会自己存储元素;
(2)不会改变源对象,会返回一个新的stream
(3)stream是延迟执行的,意味着它们会等到需要结果的时候才会执行。
Stream操作的三个步骤:
(1)创建Stream
一个数据源(集合、数组)获取一个流;
(2)中间操作
一个中间操作链,对数据源的数据进行处理;
(3)终止操作
一个终止操作,执行中间操作链,产生结果。
案例
流的获取方式
@Test public void test01(){ // 可以通过Collection集合提供stream()或parallelStearam() List<String > list = new ArrayList<>(); Stream<String> stream = list.stream(); //通过Arrays的静态方法stream()获取数组流 Employee[] employee = new Employee[10]; Stream<Employee> stream1 = Arrays.stream(employee); //通过stream类中的静态方法of() Stream<String > stream2 = Stream.of("aa","bb","cc"); //创建无限流 Stream<Integer> stream3 = Stream.iterate(0,(x)->x+2); stream3.limit(10).forEach(System.out::println); System.out.println("-------------------------------------"); Stream.generate(()->Math.random()).limit(5).forEach(System.out::println); }
中间操作与终止操作
@Test public void test02(){ List<Employee> employees = Arrays.asList(new Employee("张三",23), new Employee("李四",24), new Employee("王五",25), new Employee("王五",25)); //中间操作:不会执行任何操作 Stream<Employee> stream = employees.stream().filter((e)->{ System.out.println("Stream Api中间操作"); return e.getAge()>24; }); //终止操作:一次执行全部操作, stream.forEach(System.out::println); System.out.println("---------------------------------------"); employees.stream().filter((e)->e.getAge()>22).skip(1).forEach(System.out::println); System.out.println("-------------"); //使用distinct方法要重写equals和hashcode方法 employees.stream().filter((e)->e.getAge()>22).distinct().forEach(System.out::println); }
映射map方法和flatMap方法
@Test public void test03(){ List<String> strings = Arrays.asList("aaa","bbb","ccc"); strings.stream().map((str)->str.toUpperCase()).forEach(System.out::println); //接收lambda操作,该函数将操作应用到每个元素上 System.out.println("----------------------------------"); employees.stream().map(Employee::getAge).forEach(System.out::println); System.out.println("----------------------------------"); Stream<Stream<Character>> streamStream = strings.stream().map(StreamMain::filterChareacter);//map方法返回的是stream流 streamStream.forEach((sm)->{ sm.forEach(System.out::print); //需要嵌套for循环 }); System.out.println("----------------------------------"); Stream<Character> characterStream = strings.stream().flatMap(StreamMain::filterChareacter);//flatMap返回的是元素 characterStream.forEach(System.out::println);//不需要嵌套for循环 //map和flatMap作用的对比类似于 add和addAll方法 // Map是相当于把一个个流加入到当前流中, //FlatMap是相当于把一个个元素加入到当前流中。 Collection<Object > aList = new ArrayList(); Collection<Object > bList = new ArrayList(); bList.add("13"); bList.add("14"); aList.add("12"); aList.add(bList); System.out.println(aList); } //对字符串进行切分 public static Stream<Character> filterChareacter(String str){ List<Character> list = new ArrayList<>(); for(Character ch :str.toCharArray()){ list.add(ch); } return list.stream(); }
sorted方法
List<Employee> employees = Arrays.asList(new Employee("张三",23), new Employee("李四",24), new Employee("王五",25), new Employee("王五",25)); @Test public void test04(){ List<String > strings = Arrays.asList("aaa","ccc","bbb","ddd"); strings.stream().sorted().forEach(System.out::println); //按年龄排序 如果年龄相同则按姓名排序 employees.stream().sorted((e1,e2)->{ if(e1.getAge()==(e2.getAge())){ return e1.getUserName().compareTo(e2.getUserName()); }else { return e1.getAge().compareTo(e2.getAge()); } }).forEach(System.out::println); }
allmatch方法
@Test public void test05(){ boolean flag = employees.stream().allMatch((e)->e.getAge().equals(25)); //检查是否匹配所有元素 System.out.println(flag); boolean b2 = employees.stream().anyMatch((e)->e.getAge().equals(25)); System.out.println(b2); boolean b3 = employees.stream().noneMatch((e)->e.getAge().equals(25));//检查所有元素是否都不匹配 System.out.println(b3); Optional<Employee> first = employees.stream().sorted((e1, e2) -> -Integer.compare(e1.getAge(), e2.getAge()) ).findFirst(); System.out.println(first); Optional<Employee> any = employees.parallelStream().filter((e) -> e.getAge().equals(24)).findAny(); System.out.println(any);; }
count方法
@Test public void test06(){ Optional<Integer> min = employees.stream().map(Employee::getAge).min(Integer::compare); System.out.println(min); Optional<Employee> max = employees.stream().max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())); System.out.println(max); long count = employees.stream().count(); System.out.println(count); }
reduce 规约
//reduce 规约 //可以将流中的元素反复结合起来,得到一个值 @Test public void test07(){ List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Integer sum = nums.stream().reduce(0, (x, y) -> x + y); System.out.println(sum); Optional<Integer> sumInt = employees.stream().map(Employee::getAge) .reduce(Integer::sum); System.out.println(sumInt.get()); }
collect方法
//collect可以将流转化为其他形式 @Test public void test08(){ List<String> collect = employees.stream().map(Employee::getUserName) .collect(Collectors.toList()); System.out.println(collect); System.out.println("----------------------"); Set<String> collectSet = employees.stream() .map(Employee::getUserName) .collect(Collectors.toSet()); collectSet.forEach(System.out::println); System.out.println("---------------------------"); HashSet<String> collect1 = employees.stream().map(Employee::getUserName) .collect(Collectors.toCollection(HashSet::new)); collect1.forEach(System.out::println); } @Test public void test09(){ //总数 Long collect = employees.stream() .collect(Collectors.counting()); System.out.println(collect); //平均数 Double avg = employees.stream() .collect(Collectors.averagingInt(Employee::getAge)); System.out.println(avg); //总和 Integer sum = employees.stream() .collect(Collectors.summingInt(Employee::getAge)); System.out.println(sum); }
maxBy、minBy方法
@Test public void test10(){ Optional<Employee> collect = employees.stream() .collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()))); System.out.println(collect.get()); Optional<Integer> collect1 = employees.stream().map(Employee::getAge) .collect(Collectors.minBy(Integer::compare)); System.out.println(collect1.get()); }
分组
@Test public void teset01(){ //按照某个属性分组 Map<Integer, List<Employee>> collect = employees.stream() .collect(Collectors.groupingBy(Employee::getAge)); System.out.println(collect); System.out.println("----------------------------------"); //多级分组 Map<Integer, Map<String, List<Employee>>> collect1 = employees.stream() .collect(Collectors.groupingBy(Employee::getAge, Collectors.groupingBy((e) -> { if (((Employee) e).getSalary() > 24000) { return "有钱人"; } else { return "没钱人"; } }))); System.out.println(collect1); }
分区
//分区 @Test public void test02(){ Map<Boolean, List<Employee>> collect = employees.stream() .collect(Collectors.partitioningBy((e) -> e.getSalary() > 5000)); System.out.println(collect); }