Java流操作总结

作者: 岛上码农 | 来源:发表于2020-08-10 21:45 被阅读0次

    Java流(Stream)操作自Java 8引入,通过Stream操作可以简化代码编写,提高代码执行效率。流整体操作分为创建(Supplier)、转换、约简和收集几个操作。

    创建流

    创建流最常见的方式是调用Collection.stream()方法,将集合数据转换为流,也可以通过generate方法创建流。如下所示:

        public static void main(String[] args) {
            //从Collection中产生流
            ArrayList<String> strings = new ArrayList<>();
            for (int i = 0; i < 20; ++i) {
                strings.add("string" + i);
            }
    
            Stream<String> stringStream = strings.stream();
            show("stringStream", stringStream);
    
            //使用generate产生流
            Stream<Integer> integerStream = Stream.generate(() -> (int) (Math.random() * 100));
            show("integerStream", integerStream);
            //使用iterate产生序列
            Stream<Integer> integerStream1 = Stream.iterate(0, n -> n + 1);
            show("integerStream1", integerStream1);
    
            //使用of方法创建流
            Stream<String> stringStream1 = Stream.of("Bob", "Mark", "Alice", "Edd");
            show("stringStream1", stringStream1);
    
            //正则表达式产生流
            String sentences = "I had a dog whose name was Bingo. B, I, N, G, O, Bingo was his name, Oh!";
            Stream<String> words = Pattern.compile("\\PL+").splitAsStream(sentences);
            show("PatterStream", words);
        }
    
        public static<T> void show(String title, Stream<T> stream) {
            final int size = 10;
            List<T> array = stream.limit(size).collect(Collectors.toList());
            System.out.println(title + ": ");
            for (int i = 0; i < array.size(); ++i) {
                if (i > 0) {
                    System.out.print(", ");
                }
                if (i < array.size()) {
                    System.out.print(array.get(i));
                } else {
                    System.out.print("...");
                }
            }
            System.out.println();
        }   
    

    流的转换

    流的转换即将一个给定的流通过流的方法转换为另一个流,常见的方法有filter,map,distinct, sorted,reverse等方法。

    • filter方法保留满足filter方法中的条件表达式的元素;
    • map方法可以对流中的元素进行一个转换操作;
    • distinct方法将流中重复的元素去除
    • sorted按给定的比较方法进行排序
    String sentences = "I had a dog whose name was Bingo. B, I, N, G, O, Bingo was his name, Oh!";
    //保留长度大于2的单词
    Stream<String> words1 = Pattern.compile("\\PL+").splitAsStream(sentences).filter(s -> s.length() > 2);
    show("PatterStream1", words1);
    
    //将单词转换为大写
    Stream<String> words2 = Pattern.compile("\\PL+").splitAsStream(sentences).map(String::toUpperCase);
    show("PatterStream2", words2);
    
    //去除重复的单词
    Stream<String> words3 = Pattern.compile("\\PL+").splitAsStream(sentences).distinct();
    show("PatterStream3", words3);
    
    //按长度对单词进行排序
    Stream<String> words4 = Pattern.compile("\\PL+").splitAsStream(sentences).sorted(Comparator.comparing(String::length));
    show("PatterStream4", words4);
    
     //按长度对单词进行排序后反序
     Stream<String> words5 = Pattern.compile("\\PL+").splitAsStream(sentences).sorted(Comparator.comparing(String::length).reversed());
     show("PatterStream4", words5);
    

    流的约减(Reduce)

    流经过处理后,提供了一系列方法从流中抽取数据。抽取数据是一种终结操作,常用的方法如下:

    • count方法:获取流中满足条件的元素个数
    • min、max方法:按照给定的比较方法获取最小最大值,注意该方法返回的是一个Optional<T>的包装类,这是因为流可能为空。
    • find查找方法:包括findFirst,findAny等。
    • match方法:根据条件查找是否有匹配条件的元素,有anyMatch,allMatch和noneMatch,返回的是boolean类型。
    • 消费流:通过方法消费流中的元素,例如使用forEach迭代,传递方法处理流中的每个元素。
    • 转换为Collection或数组:通过collect方法传递Collectors类提供的toCollection方法可以转换为Collection或者调用toArray方法转换为数组。
    • 拼接:使用Collectors.join方法可以拼接流.
    • 统计,使用IntSummaryStatistics、DoubleSummaryStatistics和LongSummaryStatistics方法构造统计对象,获取 总数,平均值,最大值,最小值。需要注意调用Collectors.summarizing{Int,Double, Long}方法需要传递一个lambda表达式,确定统计的内容。
    //获取单词的数量
    long wordsCount = Pattern.compile("\\PL+").splitAsStream(sentences).filter(s -> s.length() > 2).count();
    System.out.println("Number of words length greater than 2: " + wordsCount);
    
    //获取最长的单词
    Optional<String> longestWord = Pattern.compile("\\PL+").splitAsStream(sentences).max(Comparator.comparing(String::length));
    System.out.println("longestWord: " + longestWord.orElse("null"));
    
    //获取最短的单词
    Optional<String> shortestWord = Pattern.compile("\\PL+").splitAsStream(sentences).min(Comparator.comparing(String::length));
    System.out.println("shortestWord: " + shortestWord.orElse("null"));
    
    //获取第一个以h开头的单词
    Optional<String> firstWordsStartWithH = Pattern.compile("\\PL+").splitAsStream(sentences)
                    .filter(s -> s.toLowerCase().startsWith("h")).findFirst();
    System.out.println("firstWordsStartWithH: " + firstWordsStartWithH.orElse("Not Found"));
    
    //获取任何一个以h开头的单词
    Optional<String> anyWordsStartWithH = Pattern.compile("\\PL+").splitAsStream(sentences)
                    .filter(s -> s.toLowerCase().startsWith("h")).findAny();
    System.out.println("anyWordsStartWithH: " + anyWordsStartWithH.orElse("Not Found"));
    
    //查找其中是否有was这个单词
    boolean hasWas = Pattern.compile("\\PL+").splitAsStream(sentences).anyMatch("was"::equals);
    System.out.println("hasWas: " + hasWas);
    
    //查找其中全部是was这个单词
    boolean allWas = Pattern.compile("\\PL+").splitAsStream(sentences).allMatch("was"::equals);
    System.out.println("allWas: " + allWas);
    
    //使用forEach方法打印全部单词的大写
    Pattern.compile("\\PL+").splitAsStream(sentences).map(String::toUpperCase).forEach(System.out::print);
    
    //将流转为Collection
    List<String> wordsList = Pattern.compile("\\PL+").splitAsStream(sentences).collect(Collectors.toList());
    System.out.println("wordsList: " + wordsList);
    
    //将流转为数组
    String[] wordsArray = Pattern.compile("\\PL+").splitAsStream(sentences).toArray(String[]::new);
    System.out.println("wordsArray: " + Arrays.toString(wordsArray));
    
    //将流拼接为字符串
    String wordsToSentences = Pattern.compile("\\PL+").splitAsStream(sentences).collect(Collectors.joining(", "));
    System.out.println("wordsToSentences: " + wordsToSentences);
    
    //数据统计:统计单词的长度
    IntSummaryStatistics lengthSummary = Pattern.compile("\\PL+").splitAsStream(sentences).
                    collect(Collectors.summarizingInt(String::length));
    System.out.println("Longest word length: " + lengthSummary.getMax());
    System.out.println("Shortest word length: " + lengthSummary.getMin());
    System.out.println("Average word length: " + lengthSummary.getAverage());
    
    • 收集到Map:使用Collectors.toMap转到Map数据中。
    • 分组:使用groupingBy进行分组
        public static class User {
            private String name;
            private int id;
            //1=male, 0 = female, 2= unknown
            private int sex = 2;
    
            public User(int id, String name, int sex) {
                this.id = id;
                this.name = name;
                if (sex == 0 || sex == 1) {
                    this.sex = sex;
                }
            }
    
            public int getId() {
                return id;
            }
    
            public String getName() {
                return name;
            }
    
            public int getSex() {
                return sex;
            }
    
            @Override
            public String toString() {
                return "User{id = " + id + ", name = " + name + ", sex = " + sex + "}";
            }
        }
    
        //省略部分代码...
    
        public static Stream<User> userStream() {
            return Stream.of(
                    new User(1, "Box", 1),
                    new User(2, "Succi", 0),
                    new User(3, "Lily", 0),
                    new User(4, "Sara", 0),
                    new User(5, "Mark", 1)
            );
        }
        
    
        //main方法
        public static void main(String[] args) {
            //...
            //映射为id -> User格式
            Map<Integer, User> userMap = userStream().collect(Collectors.toMap(User::getId, Function.identity()));
            for (Integer key:userMap.keySet()) {
                System.out.println("id " + key + ": " + userMap.get(key));
            }
            
            //映射为id -> User.name格式
            Map<Integer, String> idToNameMap = userStream().collect(Collectors.toMap(User::getId, User::getName));
            System.out.println(idToNameMap);
            
            //按性别分组
            Map<Integer, Set<User>> sexToUserMap = userStream().collect(Collectors.groupingBy(User::getSex, Collectors.toSet()));
            for (Integer key:sexToUserMap.keySet()) {
                Set<User> usersOfSex = sexToUserMap.get(key);
                System.out.println("Sex " + key + ": " + usersOfSex);
            }
        }
    

    相关文章

      网友评论

        本文标题:Java流操作总结

        本文链接:https://www.haomeiwen.com/subject/gkjsdktx.html