java8新特性Stream: 流水线

Stream: 流水线

流水线 : 对数据的一组操作

		jdk8,添加了新的类java.util.Stream:
		Java8中的Stream是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利高效的聚合操作,或者大批量数据操作
		Stream的API结合Lambda表达式,极大的提高编程效率和程序可读性
同时它提供串行和并行两种模式进行操作
  • 使用流

       流的使用一般包括三件事:
      	 1,一个数据源(如集合)来执行一组操作;
      	 2,一个中间操作链,形成一条流的流水线;
      	 3,一个终端操作,执行流水线,并能生成结果。
      	 4,Stream对象的构建
      		 1.使用值构建
      		Stream<String> stream = Stream.of("a", "b", "c");
      		 2. 使用数组构建
      		String[] strArray = new String[] {"a", "b", "c"};
      		Stream<String> stream = Stream.of(strArray);
      		Stream<String> stream = Arrays.stream(strArray);
      		 3. 利用集合构建(不支持Map集合)
      		List<String> list = Arrays.asList(strArray);
      		stream = list.stream();
      		 注:基本数据类型的流:IntStream ,LongStream,DoubleStream
      		不要选用Stream<Integer>,Stream<Long>,Stream<Double>因为自动装箱耗时,效率低
      		Java 8 中还没有提供其它基本类型数值的Stream
      		 4,IntStream:数值Stream的构建:
      		IntStream s1 = IntStream.of(new int[]{1, 2, 3});
      		//[1,3)
      		IntStream s2 = IntStream.range(1, 3);
      		//[1,3]
      		IntStream s3 = IntStream.rangeClosed(1, 3);
    
  • Stream转换为其它类型:

     Stream<String> stream = Stream.of("hello","world","tom");
         1,转换为Array
      	String[] strArray  = stream.toArray(String[]::new);
         2,转换为Collection
      	List<String> list1 = stream.collect(Collectors.toList());
      	List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
      	Set<String> set3 = stream.collect(Collectors.toSet());
      	Set<String> set4 = stream.collect(Collectors.toCollection(HashSet::new));
         3. 转换为String
      	String str = stream.collect(Collectors.joining()).toString();
         
         注意 : 一个 Stream 只可以使用一次,上面的代码为了简洁而重复使用了多次。
      	这个代码直接运行会抛出异常的:
      	java.lang.IllegalStateException: stream has already been operated upon or closed
    
  • 流操作

       java.util.stream.Stream中的Stream接口定义了许多操作。
       它们可以分为两大类。
         1,中间操作 : 可以连接起来的流操作
         2,终端操作 : 关闭流的操作
      	终端操作会从流的流水线生成结果。
      	其结果是任何不是流的值,比如List Integer,甚至void。
         注:除非流水线上触发一个终端操作,否则中间操作不会执行任何处理。
    
  1. 中间操作 : Intermediate

    		map
    			map(Function<? super T,? extends R> mapper)
    			返回由给定函数应用于此流的元素的结果组成的流。
    			
    			eg:把 Stream中 的每一个元素,映射成另外一个元素
    			public static void main(String[] args) throws Exception {
    				Stream<String> stream = Stream.of("tom","lisi","wangwu");
    				//R apply(T t);
    				Function<String,String> fun = (t)->t.toUpperCase();
    				List<String> list = stream.map(fun).collect(Collectors.toList());
    				System.out.println(list);
    			}
    	
    	filter : 
    		filter(Predicate<? super T> predicate)
    		返回由与此给定谓词匹配的此流的元素组成的流。
    
    		eg:获取字符串中长度大于3的字符串
    		 public static void main(String[] args) throws Exception {
    			Stream<String> stream = Stream.of("tom","lisi","wangwu","a");
    			List<String> list = stream.filter((msg)->msg.length()>3).collect(Collectors.toList());
    			// boolean test(T t);
    			// Predicate<T>
    			System.out.println(list);
    		}  
    	
    	peek : 偷看,可以用来检查流当前的状态。
    		(Consumer<? super T> action) 
    		对每个元素执行操作并返回一个新的 Stream
    		注意:调用peek之后,一定要有一个最终操作
    		public static void main(String[] args) throws Exception {
    			Stream<String> stream = Stream.of("tom","lisi","wangwu");
    			stream.filter(e -> e.length() > 3)
    				  .peek(e -> System.out.println("符合条件的值为: " + e))
    				  .collect(Collectors.toList());
    		}
    
    	distinct:
    		返回由不同元素组成的流
    	sorted:
    		返回由此流的元素组成的流,根据自然顺序排序。
    		sorted(Comparator<? super T> comparator)
    	limit:	
    		limit(long maxSize)
    		限制流的长度不超过maxSize
    		public static void main(String[] args) throws Exception {
    			Stream<String> stream = Stream.of("tom","lisi","wangwu","hhhhhh","werwerwefwe");
    			stream.filter(e -> e.length() > 3)
    				  .peek(e -> System.out.println("符合条件的值为: " + e)).limit(2)
    				  .collect(Collectors.toList());
    		}
    		满足条件的有多个,但是最终返回的集合中只有两个数据。
    	skip:	
    		skip(long n);
    		跳过多少个元素
    			public static void main(String[] args) throws Exception {
    				Stream<String> st = Stream.of("tom","lisi","wangwu","zhaoliu");
    				List<String> list = st.skip(2).collect(Collectors.toList());
    				System.out.println(list);
    			}
    		最终打印[wangwu, zhaoliu]
    
    	parallel  :  并行 
    	sequential : 有顺序
    
  2. 终端操作 : Terminal

     	forEach :
     		遍历 接收一个 Lambda 表达式,然后在 Stream 的每一个元素上执行该表达式。
     		stream.forEach(System.out::println);
     	 findFirst :
     		总是返回 Stream 的第一个元素,或者空,返回值类型:Optional。
     		如果集中什么都没有,那么list.stream().findFirst()返回一个Optional<String>对象,但是里面封装的是一个null。
     		public static void main(String[] args) throws Exception {
     			Stream<String> stream = Stream.of("hello","world","tom");
     			Optional<String> findFirst = stream.findFirst();
     			System.out.println(findFirst);
     		}
     	 
     	 anyMatch :
     		allMatch(Predicate<? super T> predicate) 
     		任意一个匹配成功返回true
     	 allMatch:
     		allMatch(Predicate<? super T> predicate) 
     		所有匹配成功才返回true
     	 noneMatch :
     		noneMatch(Predicate<? super T> predicate)
     		没有一个匹配的就返回true 否则返回false
     	 
     	 count:计数
     		返回Stream中元素的个数,返回值类型是long。
     	 
     	 reduce :合并
    
     		允许通过指定的函数来将stream中的多个元素规约合并为一个元素.
     		
     		它提供一个起始值(种子),然后依照运算规则(BinaryOperator),和前面 Stream 的第一个、第二个、第 n 个元素组合。从这个意义上说,字符串拼接、数值的 sum、min、max等都是特殊的 reduce。
     		
     		eg1:
     			1-10累加
     			IntStream red = IntStream.range(1, 10);
     			Integer sum = red.reduce(0, (a, b) -> a+b);
     			System.out.println(sum);
     		eg2:
     			拼接字符串
     			String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
     			System.out.println(concat);
     		eg3:
     			List<String> list = Arrays.asList("test","javac","hello","world","java","tom","C","javascript");
     			Optional<String> reduce = list.stream().sorted((s1,s2)->s2.length()-s1.length()).filter(s->s.startsWith("j")).map(s->s+"_briup").reduce((s1,s2)->s1+"|"+s2);
     			System.out.println(reduce.orElse("值为空"));
     			//javascript_briup|javac_briup|java_briup
     	 
     	 max:
     		max(Comparator<? super T> comparator) 
     		根据提供的 Comparator返回此流的最大元素。 
     		String[] arr= {"zom","lisi","wagnwu"};
     		Stream<String> stream = Arrays.stream(arr);
     		Optional<String> max = stream.max(String::compareTo);
     		System.out.println(max.get());//zom
     	 min:
     		min(Comparator<? super T> comparator) 
     		根据提供的 Comparator返回此流的最小元素。 
     		
     		String[] arr= {"zom","lisi","wagnwu"};
     		Stream<String> stream = Arrays.stream(arr);
     		Optional<String> max = stream.min(String::compareTo);
     		System.out.println(max.get());//lisi
     	 
     	 forEachOrdered:
     		如果流具有定义的遇到顺序,则以流的遇到顺序对该流的每个元素执行操作。 
     		Stream<String> stream = Stream.of("tom","lisi");
     		stream.forEachOrdered((a)->{System.out.println(a);});
     	 
     	 toArray :
     		toArray(IntFunction<A[]> generator) 
     		使用提供的 generator函数返回一个包含此流的元素的数组,以分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。 
     		Stream<String> stream = Stream.of("tom","lisi");
     		String[] array = stream.toArray(String[]::new);
     	 collect :
     		collect(Collector<? super T,A,R> collector) 
     		使用 Collector对此流的元素执行 mutable reduction Collector 。  
     		
     		Stream<String> stream = Stream.of("tom","lisi");
     		List<String> list = stream.collect(Collectors.toList());
     		Set<String> set = stream.collect(Collectors.toSet());
     	 findAny:
     		返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional 
     	 iterator:
     		获得迭代器
     	 
     	短路操作 : Short-circuiting: 
     				anyMatch
     				allMatch
     				noneMatch
     				findFirst
     				findAny 
     				limit
     		
     		短路 - 短路操作潜在的允许对流的操作尽早停止,而不去检查所有的元素。这是对无限流的一个特殊设计的属性;如果对流的操作没有短路,那么代码可能永远也不会终止。
     Stream.generate
     	自己来控制Stream的生成
     	这种情形通常用于随机数、常量的 Stream,或者需要前后元素间维持着某种状态信息的 Stream。
     	把 Supplier 实例传递给 Stream.generate() 生成的 Stream,由于它是无限的,在管道中,必须利用limit之类的操作限制Stream大小。
     	可以使用此方式制造出海量的测试数据
    
     eg:
     	生成100个随机数并由此创建出Stream实例
     	Stream.generate(()->(int)(Math.random()*100)).limit(100).forEach(System.out::println);
    
     工具类:Collectors 
     java.util.stream.Collectors 类
     主要作用就是辅助进行各类有用的操作。
    
     eg1:
     	把Stream中的元素进行过滤然后再转为List集合
     	List<String> list = Arrays.asList("test","hello","world","java","tom","C","javascript");
     	List<String> result = list.stream().filter(s->s.length()>4).collect(Collectors.toList());
    
  • 串行和并行:
    串行Stream上的操作是在一个线程中依次完成
    并行Stream则是在多个线程上同时执行

    串行和并行的相互转换:
    
      可以通过对收集源调用parallelStream方法来把集合转换为并行流。
      对顺序流调用parallel方法把流转换成并行流。
    
      并行流就是一个把内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
    
      对顺序流调用parallel方法并不意味着流本身有任何实际的变化。它在内部实际上就是设了一个boolean标志,表示你想让调用parallel之后进行的所有操作都并行执行。
      只需要对并行流调用BaseStream下的sequential()方法就可以把它变成顺序流。
      
    
        并行测试:
      	public static void main(String[] args) {
      	   //生成100万个不同的字符串放到集合中
      	   int max = 1000000;
      	   List<String> values = new ArrayList<String>(max);
      	   for (int i = 0; i < max; i++) {
      		   UUID uuid = UUID.randomUUID();
      		   values.add(uuid.toString());
      	   }
      	   //1纳秒*10^9=1秒 
      	   long t0 = System.nanoTime();
      	   //串行stream 
      	   long count = values.stream().sorted().count();
      	   //并行stream
      	   //long count = values.parallelStream().sorted().count();
      	   long t1 = System.nanoTime();
      	   
      	   long time = t1 - t0;
      	   System.out.println(count);
      	   System.out.println(time);
      	}
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值