• java8Stream


    Stream

    介绍

    java8添加了一个抽象流Stream,可以让我们像写sql一样操作集合元素。Stream将要处理的元素看做是一种流, 在管道中传输,并进行处理,最后由终止操作得到处理的结果。

    什么是Stream?

    Stream是一个来自特定元素队列并支持聚合操作

    • 元素是具体类型的对象,形成一个队列。
    • 数据源是流的来源。
    • 聚合操作是类似sql一样的操作,比如filter, map, reduce, find, match, sorted等。
    • Stream自己不会存储元素。
    • Stream不会改变源对象。
    • Stream操作是延迟执行的。

    创建流

    串行流

    stream():即单线程的方式去操作流

    并行流

    parallelStream():即多线程方式去操作流

    @Test
    	public void test() {
    		//1通过Collection提供的stream()和parallelStream()方法
    		List<String> list = Arrays.asList("a","b","c");
    		Stream<String> stream1 = list.stream();
    		Stream<String> stream2 = list.parallelStream();
    		
    		//2通过Arrays的静态方法stream()
    		String[] strs= {"a","b","c"};
    		Stream<String> stream3 = Arrays.stream(strs);
    		
    		//3通过Stream类中的静态方法of()
    		Stream<String> stream4 = Stream.of("a","b","c");
    		
    		//4通过Stream类的iterate方法生成无限流
    		Stream<Integer> stream5 = Stream.iterate(0, (x)->x+1);
    		
    		//5通过Stream的generate方法生成无限流
    		Stream.generate(()->Math.random());
    		
    	}
    

    中间操作

    过滤

    使用 filter(Predicate<? super T> predicate)来按照一定规则对流中元素进行过滤

    @Test
    	public void test() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5);
    		Stream<Integer> stream = list.stream();
    		stream = stream.filter((x)->x.compareTo(2)>0);
    		
    		stream.forEach(System.out::println);
    	}
    输出:
    3
    4
    5
    
    @Test
    	public void test2() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5);
    		Stream<Integer> stream = list.stream();
    		stream = stream.filter(
    				(x)->{
    			System.out.println(x);
    			return x.compareTo(2)>0;}
    			);
    	}
    结果:没有任何输出,这也就是前面说的Stream操作是延迟执行的,只有当终止操作这些中间操作才会依次执行
    

    截断

    使元素的个数不超过指定的数目

    @Test
    	public void test() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5);
    		Stream<Integer> stream = list.stream();
    		stream=stream.limit(3);
    		stream.forEach(System.out::println);
    	}
    输出:
    1
    2
    3
    可以看到只输出了给定个元素
    

    跳过元素

    跳过流中前几个元素

    @Test
    	public void test4() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5);
    		Stream<Integer> stream = list.stream();
    		stream=stream.skip(2);
    		stream.forEach(System.out::println);
    	}
    输出:
    3
    4
    5
    跳过了前两个元素
    

    唯一筛选

    两个元素通过hashCode()判断两个元素是否相同

    @Test
    	public void test5() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5,5);
    		Stream<Integer> stream = list.stream();
    		stream.distinct().forEach(System.out::println);
    	}
    输出:
    1
    2
    3
    4
    5
    

    映射

    map(method)接受一个方法,把流中的元素按照方法进行转换

    @Test
    	public void test() {
    		List<String> list = Arrays.asList("a","b","c");
    		Stream<String> stream = list.stream();
    		stream=stream.map((x)->x.toUpperCase());
    		stream.forEach(System.out::println);
    	}
    输出:
    A
    B
    C
    

    flatMap(method)也是接受一个函数作为参数,但是与map,不同的是如果这个函数生成的本来就是流,它会把函数生成流中的元素加到流中

    //这个函数本身就生成流
    public static Stream<Character> toStream(String s){
      List<Character> list=new ArrayList<Character>();
      char[] chs = s.toCharArray();
      for (char c : chs) {
        list.add(c);
      }
      Stream<Character> stream = list.stream();
      return stream;
    }
    @Test
    public void test() {
      List<String> list = Arrays.asList("aaa","bbb","ccc");
      Stream<Stream<Character>> stream = 
      //由于函数本身就生成流,所以流中加入的还是流
      list.stream().map(StreamTest::toStream);
      //遍历的时候需要先从流中取出流,在遍历
      stream.forEach((s)->s.forEach(System.out::println));
    }
    
    //然而我们可以使用flatMap进行改进
    @Test
    public void test() {
      List<String> list = Arrays.asList("aaa","bbb","ccc");
      list.stream().flatMap(StreamTest::toStream).forEach(System.out::println);
    }
    输出:
    a
    a
    a
    b
    b
    b
    c
    c
    c
    

    终止操作

    所有匹配

    当所有元素都匹配时,allMatch(Predicate<? super T> predicate)才会返回true

    @Test
    public void test() {
      List<String> list = Arrays.asList("aaa","bbb","ccc");
      boolean allMatch = list.stream().allMatch((s)->s.length()>2);
      System.out.println(allMatch);
    }
    输出:
    true
    

    任一匹配

    当Stream中任一一个元素匹配时,anyMatch(Predicate<? super T> predicate)返回true

    @Test
    public void test() {
      List<String> list = Arrays.asList("aaa","bbb","ccc");
      boolean anyMatch = list.stream().anyMatch((s)->s.equals("bbb"));
      System.out.println(anyMatch);
    }
    输出:
    true
    

    所有不匹配

    当Stream中所有的元素都不匹配时,noneMatch(Predicate<? super T> predicate)返回true

    @Test
    public void test() {
      List<String> list = Arrays.asList("aaa","bbb","ccc");
      boolean noneMatch = list.stream().noneMatch((s)->s.equals("ddd"));
      System.out.println(noneMatch);
    }
    输出:
    true
    

    第一个元素

    返回当前流中的第一个元素

    @Test
    public void test() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      Optional<Integer> findFirst = list.stream().findFirst();
      System.out.println(findFirst.get());
    }
    输出:
    1
    

    任一一个元素

    返回当前流中的任一一个元素

    @Test
    public void test() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      Optional<Integer> findAny = list.stream().findAny();
      System.out.println(findAny.get());
    }
    输出:
    1
    
    //使用并行流试试
    @Test
    public void test13() {
    	List<Integer> list = Arrays.asList(1,2,3,4,5);
    	Optional<Integer> findAny =   		list.parallelStream().findAny();
    	System.out.println(findAny.get());
    }
    输出:
    3
    

    流中元素个数

    返回流中的元素个数

    @Test
    public void test14() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      long count = list.stream().count();
      System.out.println(count);
    }
    输出:
    5
    

    流中的最大值

    返回流中元素的最大值

    @Test
    public void test15() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      Optional<Integer> max = list.stream().max(Integer::compare);
      System.out.println(max.get());
    }
    输出:
    5
    

    流中的最小值

    返回流中的最小值

    @Test
    public void test16() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      Optional<Integer> min = list.stream().min(Integer::compare);
      System.out.println(min.get());
    }
    输出:
    1
    

    规约

    将流中的元素反复结合得到一个最终值

    @Test
    public void test() {
      List<Integer> list = Arrays.asList(1,2,3,4,5);
      Optional<Integer> reduce = list.stream().reduce(Integer::sum);
      System.out.println(reduce.get());
    
      Integer reduce2 = list.stream().reduce(0, (x,y)->{
        System.out.println(x+"->"+y);
        return x+y;
      });
      System.out.println(reduce2);
    }
    输出:
    15
    0->1
    1->2
    3->3
    6->4
    10->5
    15
    

    可以看到当使用(T identity, BinaryOperator accumulator)时,identity即为最初和流中元素进行运算的,所以值不能为空,所以返回的不是Optional

    收集

    将流转换成其他形式

    @Test
    public void test() {
      List<Integer> list = Arrays.asList(1,2,3,4,5,5);
      Set<Integer> collect = list.stream().collect(Collectors.toSet());
      System.out.println(collect);
    }
    输出:
    [1, 2, 3, 4, 5]
    
    @Test
    public void test() {
    		List<Integer> list = Arrays.asList(1,2,3,4,5,5);
    		Optional<Integer> collect = list.stream().collect(Collectors.maxBy(Integer::compareTo));
    		System.out.println(collect.get());
    }
    输出:
    5
    
    class Stu{
    	String name;
    	Integer age;
    	String gender;
    	public Stu(String name, Integer age, String gender) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.gender = gender;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public Integer getAge() {
    		return age;
    	}
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    	public String getGender() {
    		return gender;
    	}
    	public void setGender(String gender) {
    		this.gender = gender;
    	}
    	@Override
    	public String toString() {
    		return "Stu [name=" + name + ", age=" + age + ", gender=" + gender + "]";
    	}
    	
    }
    //一级分组
    @Test
    	public void test() {
    		List<Stu> list = Arrays.asList(
    				new Stu("张三",20,"男"),
    				new Stu("李四",22,"女"),
    				new Stu("王五",18,"男"),
    				new Stu("赵六",20,"女"),
    				new Stu("田七",22,"女")
    				);
    		Map<String, List<Stu>> collect = 				list.stream().collect(Collectors.groupingBy(Stu::getGender));
    		System.out.println(collect);
    	}
    输出:
    {女=[Stu [name=李四, age=22, gender=女], Stu [name=赵六, age=20, gender=女], Stu [name=田七, age=22, gender=女]], 男=[Stu [name=张三, age=20, gender=男], Stu [name=王五, age=18, gender=男]]}
    
    //二级分组
    @Test
    public void test21() {
      List<Stu> list = Arrays.asList(
        new Stu("张三",20,"男"),
        new Stu("李四",22,"女"),
        new Stu("王五",18,"男"),
        new Stu("赵六",20,"女"),
        new Stu("田七",22,"女")
      );
      Map<Integer, Map<String, List<Stu>>> collect = list.stream()
        .collect(Collectors.groupingBy(Stu::getAge, Collectors.groupingBy(Stu::getGender)));
      System.out.println(collect);
    }
    输出:
    {18={男=[Stu [name=王五, age=18, gender=男]]}, 20={女=[Stu [name=赵六, age=20, gender=女]], 男=[Stu [name=张三, age=20, gender=男]]}, 22={女=[Stu [name=李四, age=22, gender=女], Stu [name=田七, age=22, gender=女]]}}
    
    //分区
    @Test
    public void test22() {
      List<Stu> list = Arrays.asList(
        new Stu("张三",20,"男"),
        new Stu("李四",22,"女"),
        new Stu("王五",18,"男"),
        new Stu("赵六",20,"女"),
        new Stu("田七",22,"女")
      );
      Map<Boolean, List<Stu>> collect = list.stream()
        .collect(Collectors.partitioningBy((e)->((Stu)e).getAge()>20));
      System.out.println(collect);
    }
    输出:
    {false=[Stu [name=张三, age=20, gender=男], Stu [name=王五, age=18, gender=男], Stu [name=赵六, age=20, gender=女]], true=[Stu [name=李四, age=22, gender=女], Stu [name=田七, age=22, gender=女]]}
    
    
  • 相关阅读:
    Regional Changchun Online--Elven Postman(裸排序二叉树)
    动态规划01背包记录
    hdoj 2546 饭卡
    hdoj 2553 N皇后问题【回溯+打表】
    nyoj 282 You are my brother
    hdoj 1231 最大连续子序列
    hdoj 1003 Max Sum
    2015年6月24
    poj 1338 Ugly Numbers
    poj 3979 分数加减法
  • 原文地址:https://www.cnblogs.com/moyuduo/p/12616827.html
Copyright © 2020-2023  润新知