java8 新特性之 Stream()的使用。

Stream 流的使用

   1,Stream 常用的 Api 
       1.1  筛选和切片: 
             
      List<String> excapleStrs = Arrays.asList("java", "java", "javaScript", "php","python","ios", "go");
     filter: 筛选
                     Streams 接口支持 filter 方法(你现在应该很熟悉了)。该操作会接受一个谓词(一个返回boolean 的函数)作为参数,并返回一个包括所有符合谓词的元素的流 .
                     筛选长度大于四的字符;            
         List<String> collect = 
excapleStrs
.stream().filter(x -> x.length() > 4).collect(Collectors.toList());
    结果为:  ["javaScript", "python"]
                     
        distinct:  去重
               流还支持一个叫作 distinct 的方法,它会返回一个元素各异(根据流所生成元素的 hashCode 和 equals 方法实现)的流,,去重。
        
excapleStrs .stream().distinct().forEach(x->System.out.println(x));      
        
结果为:  ["java", "javaScript", "php","python","ios", "go" ]

         limit: 截断
   List<String> limit = 
excapleStrs
.stream().limit(3).collect(Collectors.toList());、
   
结果为:  ["java", "java", "javaScript"]
          skip:  跳过
   List<String> skip =
excapleStrs
.stream().skip(3).collect(Collectors.toList());
结果为:  ["php","python","ios", "go"]
 
  

               1.2  映射:
它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映
射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一
个新版本”而不是去“修改”)。
 map :映射
         比如我们需要获取
excapleStrs  每个字符的长度。
 
   
    List<Integer> collect1 = strs.stream().map(String::length).collect(Collectors.toList());//方法引用
    List<Integer> collect1 = strs.stream().map(x -> x.length()).collect(Collectors.toList());//lambada表达式
flatMap: 多个流映射成一个。

你可以使用两个 map 来迭代这两个列表,并生成数对。但这样会返回一个 Stream <Stream<Integer[]>> 。
你需要让生成的流扁平化,以得到一个 Stream<Integer[]> 。这 正是 flatMap 所做的。
        //  交叉组合的方式  flatMap 组合多个Stream成为一个。
          List<Integer> numbers1 = Arrays.asList(1, 2, 3);
        List<Integer> numbers2 = Arrays.asList(3, 4);
        List<int[]> pairs =
           numbers1.stream()
                .flatMap(
                    i -> numbers2.stream().map(j -> new int[]{i, j})
                )
                .collect(Collectors.toList());
 
               1.3  查找和匹配:       
         anyMatch:   检查流中是否有一个元素匹配。
            boolean java = strs.stream().anyMatch(x -> x.equals("java")); //true
          allMatch: 流中元素必须匹配所有的。
            boolean java = strs.stream().allMatch(x -> x.equals("java")); //flase
         noneMacth: 流中没有条件元素。
            boolean java = strs.stream().noneMatch(x -> x.equals("java"));//flase
                         三个操作运用了所谓的短路,这就是大家熟悉 的Java中  &&  和  ||  运算符短路在流中的版本。
         findAny:查找任意符元素
                      findAny 方法将返回当前流中的任意元素.
           Optional<String> any = strs.stream().filter(x->x.length()>4).findAny();
           Optional的几个常用方法:  1,isPresnet() 是否有值 有返回true 否则false.
                                  2,ifPresent(Consumer<T> block) 会在值存在的时候执行给定的代码块
                                  3,T get()存在时返回值,否抛异常。
                                  4,T orElse(T other) 存在时返回值,否则返回默认的值。
    findFirst :  查找元素中的第一个
                     findAny 和 findFrist的区别是 findFirst的 查找第一个元素的并行限制很多效率不如findAny 
          1.4 归约:
         reduce 
归约
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        int sum = numbers.stream().reduce(0, (a, b) -> a + b)
reduce 接受两个参数:
   一个初始值,这里是0;
   一个 BinaryOperator<T> 来将两个元素结合起来产生一个新值,这里我们用的是
lambda (a, b) -> a + b 。
      1.5数值流
       List<Dish>  menu=[{name:"糖醋排骨",calories:350},{ name:"西红柿鸡蛋",calories:181},{ name:"鸡蛋汤",calories:95}]
              情况:求menu中的热量的和  
              ------- int allCalories   = menu.stream().map(Dish::getCalories). reduce(0,Integer::sum) ;
              这段代码的问题是,它有一个暗含的装箱成本。
              每个 Integer 都必须拆箱成一个原始类型.Java 8引入了三个原始类型特化流接口来解决这个问题:
                                 IntStream DoubleStream LongStream ,分别将流中的元素特化为 int 、 long 和 double ,从而避免了暗含的装箱成本
          优化: 
转换: lmapToInt() 
       ------menu.stream().mapToInt(Dish::getCalories).sum()
      其中mapToInt()会把Stream转换成IntStream流。 IntStream 还支持max,min,average等方法。
      转换成Stream流 在用 boxed() 方法。
                 IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
                Stream<Integer> stream = intStream.boxed();  

1-100符合的勾股数 勾股数 假如a指定值求
IntStream.rangeClosed(1, 100) .filter(b -> Math.sqrt(a*a + b*b) % 1 == 0)
.boxed().map(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)});
          这里有一个关键的假设:给出了 a 的值。 现在,只要已知 a 的值,你就有了一个可以生成勾股数的流。如何解决这个问题呢?就像 b 一样,你需要为 a 生成数值!
Stream<int[]> pythagoreanTriples = 
IntStream.rangeClosed(1, 100).boxed().
          flatMap(   a ->
              IntStream.rangeClosed(a, 100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).mapToObj(b ->new int[]{a, b, (int)Math.sqrt(a * a + b * b)}));

       目前的解决办法并不是最优的,因为你要求两次平方根。让代码更为紧凑的一种可能的方法是,先生成所有的三元数 (a*a, b*b, a*a+b*b) ,然后再筛选符合条件的:
Stream<double[]> pythagoreanTriples2 =
          IntStream.rangeClosed(1, 100).boxed().flatMap(a ->IntStream.rangeClosed(a, 100)
                        .mapToObj(b -> new double[]{a, b, Math.sqrt(a*a + b*b)}).filter(t -> t[2] % 1 == 0))
1.6构建流
            1.6.1 由值创建流  Stream.of()
                   你可以使用静态方法 Stream.of ,通过显式值创建一个流
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);

你可以使用 empty 得到一个空流,如下所示:
Stream<String> emptyStream = Stream.empty();

  1.6.2由数组创建流 Arrays.stream(List  list).
 int[] numbers = {2, 3, 5, 7, 11, 13};
 int sum = Arrays.stream(numbers).sum();

 1.6.3由文件生成流  Files.lines ()
           数数文件中有多少各不相同的单词
 
  
long uniqueWords = 0;
try(Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())){
    uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
            .distinct().count();
}
catch(IOException e){
     //throw  new  Exception(e);
}

你可以使用 Files.lines 得到一个流,其中的每个元素都是给定文件中的一行
1.6.4 由函数生成流
由 iterate 和 generate 产生的流会用给定的函数按需创建值,因此可以无穷无尽地计算下去!一般来说, 应该使用 limit(n) 来对这种流加以限制,以避免打印无穷多个值
1. 迭代 Stream.iterate()
我们先来看一个 iterate 的简单例子,然后再解释:
        Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
iterate 方法接受一个初始值(在这里是 0 ),还有一个依次应用在每个产生的新值上的
Lambda( UnaryOperator<t> 类型)。这里,我们使用Lambda  n -> n + 2 ,我们使用 limit 方法来显式限制流的大小。这里只选择了前10个偶数.

2.生成  Stream.generate()
        Stream.generate(Math::random).limit(5).forEach(System.out::println);

      generate它接受一个 Supplier<T> 类型的Lambda提供新的


                                                                                                                                                         

转载请 标明地址。本文可能有错误或者不足 请大家指出。 本博客是根据《java8实战》的总结笔记。更多内容可以查看此书。

                                                                                                                                 

                                                                                                                                        -----------------BY   DavinQi 。



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java 8引入了Stream API,它是一种新的处理集合的方式,可以用更简洁、更易读的代码处理集合数据。Stream API提供了非常方便的、高效的数据处理方式,包括筛选、排序、映射、归约等。 下面是一些Stream的常用操作: 1. filter():筛选符合条件的元素 ```java List<String> list = Arrays.asList("apple", "orange", "banana", "pear", "peach"); List<String> result = list.stream().filter(str -> str.contains("e")).collect(Collectors.toList()); ``` 2. map():将元素转换成其他形式或提取信息 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().map(num -> num * num).collect(Collectors.toList()); ``` 3. sorted():对元素进行排序 ```java List<Integer> nums = Arrays.asList(5, 3, 1, 2, 4); List<Integer> result = nums.stream().sorted().collect(Collectors.toList()); ``` 4. distinct():去重 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 3, 4, 4, 5); List<Integer> result = nums.stream().distinct().collect(Collectors.toList()); ``` 5. limit():截取流中前n个元素 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().limit(3).collect(Collectors.toList()); ``` 6. skip():跳过流中前n个元素 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); List<Integer> result = nums.stream().skip(3).collect(Collectors.toList()); ``` 7. reduce():将流中元素归约为一个值 ```java List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5); int result = nums.stream().reduce(0, (a, b) -> a + b); ``` 这些操作只是Stream API中的一部分,还有很多其他操作可以使用Stream API可以让我们更加方便地处理集合数据,提高开发效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值