zoukankan      html  css  js  c++  java
  • Java之Stream流


    流在java的官方文档中被定义为视图。通过流去完成什么样的任务,而不是如何去实现它。通俗一点来讲它相对于集合就是表达了做什么,而不是怎么做。
    流和集合的差异
    1.流并不储存数据,数据还是储存在底层的集合中。
    2.流的操作并不能修改数据,它只是在原本的流中产生新的流。
    3.流的操作是惰性的,只要不使用终结方法提交操作我们就可以一直无限流。

    流有
    stream() //流 将任何集合转换为一个流
    parallelStream() //并行流、顺序流

    流的创建

    Stream<String> words = Stream.of(contents.split("\PL+")); //将数组转换成为流
    Stream<String> silence = Stream.empty();    //创建一个没有任何元素的流
    
    Stream<String> echos = Stream.generate(() -> "Echo");    //创建一个常量值的流
    Stream<Double> randoms = Stream.generate(Math :: random);    //获取一个随机数的流
    
    //产生一个无限流,在它的值上产生新的值、在前一个元素上调用后一个方法产生值
    Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO, n -> n.add(BigInteger.ONE));

    filter、map 和 flatMap 方法

    //过滤产生新的流
    List<String> wordList = ...;
    Stram<String> longWords = wordList.stream().filter(w -> w.length() > 12);
    
    //用map转换成新的流
    Stream<String> lowercaseWords = words.stram().map(String :: toLowerCase);
    Stream<String> firsLetters = words.stram().map(s -> s.substring(0, 1));
    
    //用flatMap 将所有当前流中所有元素连接到一起
    Stream<String> flatResult = words.stream().flatMap(w -> ... );

    抽取子流和连接流

    //获取一个限制大小的流
    Stream<Double> randows = Stream.generate(Math :: random).limit(100);
    //丢弃前n个元素
    Stream<String> words = Stream.of(contents.split("\PL+")).skip(1);
    //连接两个元素的流
    Stream<String> combined = Sream.concat( ... , ...);

    其他的流转换

    //剔除重复元素的流
    Stream<String> uniqueWords = Stream.of("a", "a", "b", "c").distinct();
    //对流进行排序
    Stream<String> longesFirst = words.stram().sorted(Comparator.comparing(String :: length).reversed());
    //peek 产生和原来的流相同,但是每次获取一个元素时都调用一次函数
    Object[] powers = Stream.iterate(1.0, p -> p*2).peek(e -> System.out.println("Fetching" + e)).limit(20).toArray();

    简单约简
    约简是一种终结操作。

    //获取最大值
    Optional<String> largest = words.max(String :: compareToIgnoreCase);

    Optional<T>类型
    Optional<T>对象是一种包装器对象,要么包装了T类型的对象,要么没有包装任何对象。
    如何使用Optional值

    //没有任何匹配的时候返回空字符串
    String result = optionalString.orElse("");
    //计算默认值
    String result = optionalString.orElseGet(() -> Locale.getDefault().getDisplayName());
    //没有任何值时抛出异常
    String result = optionalString.orElseThrow(IllegalStateException :: new);
    
    //如果值存在将它添加进某个集中
    optionalVlaue.ifPresent(v -> results.add(v));
    //
    optionalValue.ifPresent(results :: add);
    
    ifPresent不会返回任何值,如果想处理函数结果过应该使用map
    //added 可能存在三种值,true、false、空的Optional
    Optional<Boolean> added = optionalValue.map(results :: add);

    不适合使用OPtional值的方式
    在Optional值为null使用get将会抛出NoSuchElementException对象。
    所以不要直接使用get()方法,应先判断值是否存在。

    if(optionalValue.isPresent())
    optionalValue.get().someMethod();
    //
    if(vlaue != null)
    value.someMethod();

    创建Optional值

    Optional.of(result)和Optional.empty()

    public static Optional<Double> inverse(Double x)
    {
    return x == 0 ? Optional.empty() : Optional.of(1/X);
    }

    ofNullable方法
    ofNullable(obj)会在obj不为null 的情况返回Optional.of(obj),否则返回Optional.empty()。

    用flatMap来构建Optional值的函数
    flatMap就像是管道,在Optional<T>对象的方法f有产生另外的Optional<U>对象g时不能直接调用s.f().g()。
    因为它们属于不同类型的Optional<T>。则是就可以用到flatMap。

    Optional<U> result = s.f().flatMap(T :: g)

    收集结果
    当处理完流之后,想要获取里面的元素是。可以调用iterator方法或者forEach
    stream.forEach(System.out :: println);
    在并行流上,forEach方法会以任意顺序遍历。如果想按流中的顺序可以调用forEachOrdered方法。
    更多的是转变成为一种数据结构。可以调用toArray。
    收集到数组中
    因为无法在运行时创建泛型数组,所以steam.toArray()会返回一个Object[]数组。
    如果想正确创建指定类型数组。

    String[] result = stream.toArray(String[] :: new);

    收集到集合中

    List<String> result = stream.collect(Collectors.toList());
    //
    Set<String> result = stream.collect(Collectors.toSet());
    //如果想指定集合种类
    TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet :: new));

    连接流中所有字符串

    String result = stream.collect(Collectors.joinjing());
    //想加分割符
    String result = stream.collect(Collectors.joinjing(","));
    //如果不是字符串,得先转成字符串
    String result = stream.map(Object :: toString).collect(Collectors.joining(","));

    对流的结果约简为总和、平均值、最大值或最小值

    IntSummaryStatistics summary = stream.collect(Collectors.summarizingInt(String :: length));
    double averageWordLength = summary.getAverage();
    double maxWordLength = summary.getMax();


    收集到映射表中
    假设有Stream<Person>

    Map<Integer, String> idToName = people.collect(Collectors.toMap(Person :: getId, Person :: getName));
    //第二值也可使用函数
    Map<Integer, String> idToName = people.collect(Collectors.toMap(Person :: getId, Function.identity()));

    如果有多个元素相同的键将会抛出IllegalStateExcpetion对象
    这时可以使用第三个函数来处理冲突

    Stream<Locale> locale = Stream.of(Locale.getAvailableLocales());
    Map<String, String> languages = locales.collect(
        Collectors.toMap(
          Locale :: getDisplayLanguage,
          l -> l.getDisplayLanguage(l),
          (existingValue, newValue) -> existingValue
      )
    );

    群组和分区
    groupingBy一种更方便的方法,它会见现有的集与新集合并。

    Map<String, List<Locale>> countryToLocales = locales.collect(Collectors.groupingBy(Locale :: getCountry));
    List<Local> swissLocales = countryToLocales.get("CH");

    分类函数是断言函数,在这种情况下使用partitioningBy比使用groupingBy更高效

    Map<Boolean, List<Locale>> englishAanOtherLocales = locales.collect(
    Collectors.partitioningBy(l -> l.getLanguage().equals("en")));
    List<Local> englishLocales =englishAndToLocales.get(true);

    groupingByConcurrent方法使用并行流时可获得并行映射表与toConcurrentMap方法类似。

    下游收集器

    //groupingBy产生的映射表,它的每个值是列表,想获得集就得
    Map<String, Set<Locale>>countryToLocaleSet = locales.collect(groupingBy(Locale :: getCountry, toSet()));
    //counting收集元素个数
    Map<String, Long> countryToLocalCounts = locales.collect(groupingBy(Locale :: getCountry, counting()));
    //summing(Int|Long|Double) 接受引元,产生它们的和
    Map<String, Integer> stateToCityPopulation = locales.collect(
      groupingBy(City :: getState, summingInt(City :: getPopulation)));
    //maxBy、minBy获取最大、小值
    Map<String, Optional<City>>stateToLargestCity = cities.collect(
      groupingBy(City :: getState, maxBy(Comparator.comping(City :: getPopulation))));
    //mapping方法使用函数
    Map<String, Optional<String>> stateToLargestCityName = cities.collect(
      groupingBy(City :: getState, mapping(City :: getName, maxBy(Comparator.comping(String :: length)))));
    //mapping方法收集到集
    Map<String, Set<String>> countryToLanguages = locales.collect(
      groupingBy(Locale :: getDisplayCountry, mapping(Locale :: getDisplayLanguage, toSet())));
    //IntSummaryStatistics使用汇总(适用int、long、double)
    Map<String, IntSummaryStatistics> stateToCityPopulationSummary = cities.collect(
      groupingBy(Ctiy :: getState, summarizing(Ctiy :: getPopulation)));
  • 相关阅读:
    JAVA中的流-简介(二)
    JAVA中的流-简介(一)
    Java中内部类简介
    应用小练习-自定义栈
    集合知识点(二)
    集合知识点(一)
    JAVA中的正则表达式简介
    从头文件中学习sfr和sbit
    PCB中实现元器件旋转一个角度放置
    DXP中插入LOGO字体方法(2)
  • 原文地址:https://www.cnblogs.com/ic710/p/11490728.html
Copyright © 2011-2022 走看看