Java基础复习 Day 26

Java基础复习 Day 26

Stream

  1. Stream的引入

    对于Stream,是Java8的新特性,并不是之前学过的I/O流,而是通过对集合,数组等进行批量操作后从而简化以前对数组,集合复杂的计算。

    • 传统集合的操作:发现总是在对集合进行循环遍历,或者各种数据的筛选操作时,对于批量数据来说,这种循环的方式显得比较效率低。

      public static void main(String[] args) {
              List<String> strs = new ArrayList<>();
              strs.add("KarenKou");
              strs.add("Kyle");
              strs.add("Steven");
              strs.add("Kevin");
              strs.add("Shelly");
              strs.add("James");
              //对集合中的元素进行遍历,把以K开头的名字储存在strsK中
              List<String> strsK = new ArrayList<>();
              for (String str:
                   strs) {
                 if (str.startsWith("K")){
                     strsK.add(str);
                 }
              }
              //对集合中的元素再进行遍历,把strsK中的长度>5的名称给过滤掉,新数据存储在strsNew1中
              List<String> strsNew1 = new ArrayList<>();
              for (String str:
                   strsK) {
                  if(str.length()>5){
                      strsNew1.add(str);
                  }
              }
              //遍历最新的集合,进行输出
              for (String str:
                   strsNew1) {
                  System.out.println(str);
              }
          }
      
    • 用Stream,专注于做什么,而不是怎么做,来进行遍历

       public static void main(String[] args) {
              List<String> strs = new ArrayList<>();
              strs.add("KarenKou");
              strs.add("Kyle");
              strs.add("Steven");
              strs.add("Kevin");
              strs.add("Shelly");
              strs.add("James");
              //用stream流的思想对集合中的元素进行遍历,把以K开头的名字储存在strsK中
              Stream<String> strsk = strs.stream().filter((name) -> {
                  return name.startsWith("K");
              });
              //对集合中的元素再进行遍历,把strsK中的长度>5的名称给过滤掉,新数据存储在strsNew1中
              Stream<String> strsNew1 = strsk.filter((name) -> name.length() > 5);
              //遍历最新的集合,进行输出
              strsNew1.forEach((name) -> System.out.println(name));//KarenKou
           	//终极大法,链式编程
           	strs.stream().filter((name) -> name.startsWith("K")).filter((name) -> name.length()>5).forEach((name) -> System.out.println(name));//KarenKou
          }
      
  2. Stream流式思想

    • Stream流式模型(图片来自某网课,侵权请联系删除)

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYuKYKx6-1661334944861)(C:\Users\Karen\Desktop\MarkDown 学习\Java基础复习笔记\day26\Stream Model.png)]

      这里的filter,map,skip都是在对函数模型来进行操作,集合元素并没有被真正处理,只有当终结方法count执行的时候,整个模型才会按照指定的策略来进行动作,

    在这里插入图片描述

    • 获取流

      1. 获取流的方式

        java.util.stream.Stream<T>是Java8新加入的最常用的stream流接口(但并不是函数式接口)

        获取流的方式有两种

        • 所有的Collection集合都可以通过Stream默认方法来获取流

          首先,java.util.stream.Collection接口中加入了default方法 stream来获取流,所以所有的Collection接口的实现类均可以通过此方法获取流

          default Stream<E> stream()

              /**
               * Returns a sequential {@code Stream} with this collection as its source.
               *
               * <p>This method should be overridden when the {@link #spliterator()}
               * method cannot return a spliterator that is {@code IMMUTABLE},
               * {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()}
               * for details.)
               *
               * @implSpec
               * The default implementation creates a sequential {@code Stream} from the
               * collection's {@code Spliterator}.
               *
               * @return a sequential {@code Stream} over the elements in this collection
               * @since 1.8
               */
              default Stream<E> stream() {
                  return StreamSupport.stream(spliterator(), false);
              }
          
        • Stream接口的静态方法of可以获取流

          /**
           * Returns a sequential {@code Stream} containing a single element.
           *
           * @param t the single element
           * @param <T> the type of stream elements
           * @return a singleton sequential stream
           */
          public static<T> Stream<T> of(T t) {
              return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
          }
          
          /**
           * Returns a sequential ordered stream whose elements are the specified values.
           *
           * @param <T> the type of stream elements
           * @param values the elements of the new stream
           * @return the new stream
           */
          @SafeVarargs
          @SuppressWarnings("varargs") // Creating a stream from an array is safe
          public static<T> Stream<T> of(T... values) {
              return Arrays.stream(values);
          }
          
        • public static void main(String[] args) {
                  //把集合转换为Stream流
                  List<String> lists = new ArrayList<>();
                  lists.add("Karen");
                  lists.add("Kyle");
                  lists.add("Kate");
                  lists.add("Kevin");
                  Stream<String> stream1 = lists.stream();
                  Set<String> set = new HashSet<>();
                  Stream<String> stream2 = set.stream();
                  //对于双列集合,可以间接利用key值和获取值的set集合来获取流
                  Map<String,String> map = new HashMap<>();
                  //获取键
                  Set<String> keys = map.keySet();
                  Stream<String> stream3 = keys.stream();
                  //获取值
                  Collection<String> values = map.values();
                  Stream<String> stream4 = values.stream();
                  //或者获取键值对(键与值的对应关系)
                  Set<Map.Entry<String, String>> entries = map.entrySet();
                  Stream<Map.Entry<String, String>> stream5 = entries.stream();
          
                  //把数组也可以获取流 通过Stream中的静态方法of
                  Integer[] arrs = {1,2,3,4,5};
                  Stream<Integer> stream6 = Stream.of(arrs);
                  
              }
          
      2. Steam中的常用方法(侵权联系删除)

        在这里插入图片描述
        在这里插入图片描述

        • 逐一处理 forEach

          void forEach(Consumer<? super T> action);用来遍历流中的数据,逐一处理流元素的语句,该方法是一个终结方法,遍历之后不可再调用其他的流方法

          public static void main(String[] args) {
              Stream<String> stream1 = Stream.of("Karen", "Leonard", "Sheldon", "Kyle");
              stream1.forEach((name) -> System.out.print(name + " "));//Karen Leonard Sheldon Kyle 
          }
          
        • 过滤:filter方法

          Stream<T> filter(Predicate<? super T> predicate);通过过滤形成一个新的不同的子流

          public static void main(String[] args) {
              Stream<String> stream1 = Stream.of("Karen", "Leonard", "Sheldon", "Kyle");
             //对名字进行过滤,只要以K开头的名字
              Stream<String> stream2 = stream1.filter((name) -> name.startsWith("K"));
              stream2.forEach((name)-> System.out.print(name + " "));//Karen Kyle
          }
          
        • Stream流的特点:Stream流式一个管道流,只能被消费(使用)一次,第一个Stream调用完方法时就会被关闭,数据流就会流向下一个Stream,此时再使用第一个stream调用方法时就会抛异常。

          public static void main(String[] args) {
              Stream<String> stream1 = Stream.of("Karen", "Leonard", "Sheldon", "Kyle");
             //对名字进行过滤,只要以K开头的名字
              Stream<String> stream2 = stream1.filter((name) -> name.startsWith("K"));
              stream2.forEach((name)-> System.out.print(name + " "));//Karen Kyle
              stream1.forEach((name) -> System.out.println(name) );//抛异常
              //Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
              // at java.util.stream.AbstractPipeline.sourceStageSpliterator(AbstractPipeline.java:279)
              // at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
              // at com.kou.stream.demo1.DemoStreamMethod2.main(DemoStreamMethod2.java:11)
          }
          
        • 映射:map方法 用来将stream流的类型做一个转换

          <R> Stream<R> map(Function<? super T, ? extends R> mapper);

          public static void main(String[] args) {
              Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
              //把Integer类型的stream转换成String类型的stream
              Stream<String> stream1 = stream.map((Integer a) -> a.toString());
              stream1.forEach((str) -> System.out.println(str));
          }
          
        • count方法

          long count(); 用来统计流中元素的个数 注意:返回值是long类型 并且该方法是终结方法

          public static void main(String[] args) {
              List<String> lists = new ArrayList<>();
              lists.add("Karen");
              lists.add("Kate");
              lists.add("Kyle");
              lists.add("Penny");
              long count = lists.stream().count();
              System.out.println(count);
          }
          
        • 取用前几个:limit方法

          Stream<T> limit(long maxSize); 对流进行截取,只截取前几个,参数是long型,如果当前集合的长度大于maxSize则截取,否则不进行操作。

          public static void main(String[] args) {
              List<String> lists = new ArrayList<>();
              lists.add("Karen");
              lists.add("Kate");
              lists.add("Kyle");
              lists.add("Penny");
              //limit是一个延迟方法,所以仍然可以继续链式调用其他方法
              lists.stream().limit(3).forEach(s -> System.out.print(s + ", "));//Karen, Kate, Kyle,
          }
          
        • 跳过前几个:skip方法

          Stream<T> skip(long n);如果希望跳过前几个方法,可以通过使用skip方法来获取一个截取之后的新流

          如果当前的流的元素长度大于n,则跳过前n个,乳沟当前长度小于n,那么使用skip之后将会得到一个长度为0的空流

          public static void main(String[] args) {
              List<String> lists = new ArrayList<>();
              lists.add("Karen");
              lists.add("Kate");
              lists.add("Kyle");
              lists.add("Penny");
              //skip是一个延迟方法,所以仍然可以继续链式调用其他方法
              lists.stream().skip(2).forEach((s -> System.out.print(s + " ")));//Kyle Penny 
          }
          
        • 组合方法:concat方法,如果希望将两个流合并为一个流,那么可以使用concat方法将两个流合并

          注意:concat是Stream的静态方法 与String中的同名方法时不一样的。

          public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
              Objects.requireNonNull(a);
              Objects.requireNonNull(b);
          
              @SuppressWarnings("unchecked")
              Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
                      (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
              Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
              return stream.onClose(Streams.composedClose(a, b));
          }
          
             public static void main(String[] args) {
                  List<String> lists = new ArrayList<>();
                  lists.add("Karen");
                  lists.add("Kate");
                  lists.add("Kyle");
                  lists.add("Penny");
                  //skip是一个延迟方法,所以仍然可以继续链式调用其他方法
                  List<String> lists2 = new ArrayList<>();
                  lists.add("Sheldon");
                  lists.add("Leonard");
                  lists.add("Raji");
                  lists.add("Howard");
                  Stream<String> stream1 = lists.stream();
                  Stream<String> stream2 = lists2.stream();
                  Stream<String> stream3 = Stream.concat(stream1, stream2);
                  stream3.forEach((s)-> System.out.print(s + " "));//Karen Kate Kyle Penny Sheldon Leonard Raji Howard 
          
              }
          
        • Collection练习 使用传统方法和Stream流式的思想

          • 传统方式 不停的for循环

             public static void main(String[] args) {
                    List<String> lists1 = new ArrayList<>();
                    List<String> lists11 = new ArrayList<>();
                    List<String> lists12 = new ArrayList<>();
                    lists1.add("Karen");
                    lists1.add("Kate");
                    lists1.add("Kyle");
                    lists1.add("Penny");
                    lists1.add("Kevin");
                    lists1.add("Karl");
                    for (String list : lists1) {
                        if (list.length()==4) {
                            lists11.add(list);
                        }
                    }
                    for (int i = 0; i < 3; i++) {
                        lists12.add(lists11.get(i));
                    }
                    List<String> lists2 = new ArrayList<>();
                    List<String> lists21 = new ArrayList<>();
                    List<String> lists22 = new ArrayList<>();
                    List<String> listsNew = new ArrayList<>();
                    List<Person> persons = new ArrayList<>();
                    lists2.add("Sheldon");
                    lists2.add("Leonard");
                    lists2.add("Raji");
                    lists2.add("Hoaward");
                    lists2.add("Lucy");
                    lists2.add("Kate");
                    for (String list2:
                         lists2) {
                      if (list2.length()>4) {
                          lists21.add(list2);
                      }  
                    }
                    for (int i = 2; i < lists21.size(); i++) {
                        lists22.add(lists21.get(i));
                    }
                    for (String s : lists12) {
                        listsNew.add(s);
                    }
                    for (String s : lists22) {
                        listsNew.add(s);
                    }
                    for (String s : listsNew) {
                        persons.add(new Person(s));
                    }
                    for (Person person : persons) {
                        System.out.print(person + " ");
                        //Person{name='Kate'} Person{name='Kyle'} Person{name='Karl'} Person{name='Hoaward'} 
                    }
                }
            
          • Stream流式思想

            public static void main(String[] args) {
                    List<String> lists1 = new ArrayList<>();
                    lists1.add("Karen");
                    lists1.add("Kate");
                    lists1.add("Kyle");
                    lists1.add("Penny");
                    lists1.add("Kevin");
                    lists1.add("Karl");
                    List<String> lists2 = new ArrayList<>();
                    lists2.add("Sheldon");
                    lists2.add("Leonard");
                    lists2.add("Raji");
                    lists2.add("Hoaward");
                    lists2.add("Lucy");
                    lists2.add("Kate");
                    Stream<String> stream1 = lists1.stream().filter((name) -> name.length() == 4).limit(3);
                    Stream<String> stream2 = lists2.stream().filter((name) -> name.length() > 4).skip(2);
                    Stream<String> stream3 = Stream.concat(stream1, stream2);
                    //stream3.forEach((name) -> System.out.print(new Person(name) + " "));
                    //Person{name='Kate'} Person{name='Kyle'} Person{name='Karl'} Person{name='Hoaward'}
                    //将string类型的stream转换成People类型的stream
                    stream3.map((name) -> new Person(name)).forEach(person -> System.out.print(person + " "));
                    //Person{name='Kate'} Person{name='Kyle'} Person{name='Karl'} Person{name='Hoaward'} 
            
                }
            
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值