Stream API 详解和25道练习题

Stream API是 Java 8 引入的一种新特性,用于简化集合操作,支持函数式编程,便于并行处理,具有延迟计算的特点。

Stream API的优势在于代码简洁、内置丰富的操作,能够提高数据处理效率。

流的操作分为三个步骤:它包括创建流中间操作(如过滤、映射、排序等)和终止操作(如遍历、汇总、转换等),实现对集合的高效处理。


目录

一、什么是 Stream API

二、Stream API 的优势

三、什么是流

四、Stream 的三个操作

1.  创建流

2.  中间操作

3.  终止操作

五、Stream API 的练习

1. 基础练习

(1)计算整数列表的总和

(2)找出整数列表中的最大值

(3)计算整数列表中所有偶数的平均值

(4)筛选出一个整数列表中的偶数并打印

(5)将字符串列表中的每个元素转换为大写并收集到新的列表

(6)对整数列表进行降序排序,并获取前3个元素

(7)将整数列表中的每个数字乘以2,并收集到一个新的列表中

(8)检查整数列表中是否所有数字都是正数

(9)找出整数列表中大于5的最小值

(10)检查整数列表中是否存在至少一个数字大于10

(11)检查整数列表中是否包含连续的数字

(12)将整数列表中的数字进行去重

(13)从字符串列表中找出最长的字符串

2. 进阶练习

(14)从员工(姓名、年龄)列表中找出年龄大于30岁的员工姓名列表

(15)计算列表中每个元素出现的次数

(16)对字符串列表按单词长度进行分组,并打印出每个长度组的单词列表

(17)将整数列表中的数字分为奇数和偶数,分别存储在不同的列表中

(18)将一个字符串列表中的每个字符串长度求和

(19)对员工列表按年龄分组,并打印每个年龄组的人数

(20)计算字符串中每个字符出现的次数

(21)给定两个字符串列表,合并这两个列表,并去除重复项,然后按字母顺序排序

(22)将字符串列表转换为Map,其中键是字符串,值是字符串长度


进阶知识:Collectors

可参考 Collectors 详解-CSDN博客

一、什么是 Stream API

Stream API 是 Java 8 引入的一个新特性,它提供了一种处理集合的新方式,可以更简洁、更易读地操作数据。Stream API 可以用来处理集合中的元素,类似于使用 SQL 进行查询,可以进行过滤、映射、排序、聚合等操作。

以下是Stream API的一些关键概念:

  1. 源:Stream可以是从集合、数组、文件等生成的。
  2. 中间操作:诸如filter、map、sorted等操作会返回一个新Stream,这些操作不会修改原始数据源,它们返回的是一个新的Stream作为结果。
  3. 终端操作:诸如forEach、collect、reduce等操作,这些操作会返回一个结果或者一个副作用,比如对集合进行遍历、汇总或者转换成其他形式。

二、Stream API 的优势

  1. 支持函数式编程:Stream API 基于函数式接口,可以使用 Lambda 表达式来传递行为,使得代码更为灵活和可维护。
  2. 便于并行处理:Stream API 内置支持并行处理,并且可以利用多核架构来提高性能。通过 parallel() 方法可以轻松地将串行流转换为并行流。
  3. 延迟计算:Stream 中的操作可以进行延迟计算,只有在需要结果时才会执行。这种特性使得 Stream 在处理大数据集时能够有效地优化性能。
  4. 代码简洁:Stream API 提供了一套函数式编程风格的方法,使得代码更为简洁,可以通过链式操作完成复杂的数据处理任务。
  5. 内置丰富的操作:Stream API 提供了丰富的中间操作(如 filter、map、sorted 等)和终端操作(如 forEach、collect、reduce 等),可以满足各种数据处理需求。

三、什么是流

流(Stream)是一种数据通道,它用于处理数据源(如集合、数组等)所产生的元素序列。“集合关注的是数据本身,而流关注的是对数据的计算处理。”             

四、Stream 的三个操作

1.  创建流

  • Stream.of(T… values):通过显式值创建一个流。
  • Collection.stream():通过集合的stream()方法创建一个流。
  • Collection.parallelStream():通过集合的parallelStream()方法创建一个并行流。
  • Arrays.stream(T[] array):通过数组创建一个流。
  • Stream.iterate(T seed, UnaryOperator f):创建一个无限流,种子值是seed,后续元素通过函数f迭代生成。
  • Stream.generate(Supplier s):创建一个无限流,元素通过Supplier函数生成。
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Stream;
import java.util.function.UnaryOperator;
import java.util.function.Supplier;

public class Main {
    public static void main(String[] args) {
        // Stream.of(T… values) 通过显式值创建一个流
        Stream<String> streamOfValues = Stream.of("a", "b", "c");
        streamOfValues.forEach(s -> System.out.print(s + " "));
        // a b c
        System.out.println();

        // Collection.stream() 通过集合的stream()方法创建一个流
        Collection<String> collection = Arrays.asList("x", "y", "z");
        Stream<String> streamFromCollection = collection.stream();
        streamFromCollection.forEach(s -> System.out.print(s + " "));
        // x y z
        System.out.println();

        // Collection.parallelStream() 通过集合的parallelStream()方法创建一个并行流
        Stream<String> parallelStreamFromCollection = collection.parallelStream();
        parallelStreamFromCollection.forEach(s -> System.out.print(s + " "));
        // y x z
        System.out.println();

        // Arrays.stream(T[] array) 通过数组创建一个流
        String[] array = {"1", "2", "3"};
        Stream<String> streamFromArray = Arrays.stream(array);
        streamFromArray.forEach(s -> System.out.print(s + " "));
        // 1 2 3
        System.out.println();

        // Stream.iterate(T seed, UnaryOperator f) 创建一个无限流,种子值是0,后续元素通过函数f迭代生成
        UnaryOperator<Integer> f = x -> x + 2;
        Stream<Integer> iterateStream = Stream.iterate(0, f);
        iterateStream.limit(5).forEach(s -> System.out.print(s + " ")); // 限制输出前5个元素
        // 0 2 4 6 8
        System.out.println();

        // Stream.generate(Supplier s) 创建一个无限流,元素通过Supplier函数生成
        Supplier<Double> randomSupplier = Math::random;
        Stream<Double> generateStream = Stream.generate(randomSupplier);
        generateStream.limit(3).forEach(s -> System.out.print(s + " ")); // 限制输出前3个元素
        // 0.5262200929887488 0.07660005625390776 0.5097922636483587 
        System.out.println();
    }
}

2.  中间操作

  • filter(Predicate predicate):过滤流中的元素,只保留满足条件的元素。

  • map(Function<T, R> mapper):转换每个元素到对应的结果。

  • mapToInt(ToIntFunction mapper):转换元素为int类型。

  • mapToLong(ToLongFunction mapper):转换元素为long类型。

  • mapToDouble(ToDoubleFunction mapper):转换元素为double类型。

  • flatMap(Function<T, Stream> mapper):将每个元素转换为另一个流,然后将这些流连接成一个流。

  • distinct():返回一个元素各不相同的新流。

  • sorted():返回一个自然排序后的流。

  • sorted(Comparator comparator):返回一个按照指定比较器排序后的流。

  • peek(Consumer action):对每个元素执行操作,并返回一个新的流。

  • limit(long maxSize):截断流,使其元素不超过指定数量。

  • skip(long n):跳过前n个元素,返回剩下的元素组成的流。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class Main {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");

        // filter:过滤流中的元素,只保留满足条件的元素
        List<String> filtered = strings.stream() //Collection.stream()集合方式创建流,得到的元素类型Stream<String>
                .filter(s -> !s.isEmpty())//筛选出不为空的字符串,不改变流的类型
                .collect(Collectors.toList()); //终止操作,把stream流中的每个元素收集到List集合中
        System.out.println("Filtered: " + filtered); //Filtered: [abc, bc, efg, abcd, jkl]

        // map:转换每个元素到对应的结果
        List<Integer> lengths = strings.stream()
                .map(s -> s.length())//对每个元素进行映射,s -> s.length()也可改写成String::length,得到元素类型Stream<Integer>
                .collect(Collectors.toList());
        System.out.println("Lengths: " + lengths); //Lengths: [3, 0, 2, 3, 4, 0, 3]

        // mapToInt:转换元素为int类型
        int[] intLengths = strings.stream()
                .mapToInt(String::length)//对生成的元素转换为int类型,得到IntStream类型的流
                .toArray();//终止操作,把stream流中的每个元素收集到数组中
        System.out.println("Int Lengths: " + Arrays.toString(intLengths));//Int Lengths: [3, 0, 2, 3, 4, 0, 3]

        // mapToLong:转换元素为long类型
        long[] longLengths = strings.stream()
                .mapToLong(String::length)//对生成的元素转换为long类型,得到LongStream类型的流
                .toArray();
        System.out.println("Long Lengths: " + Arrays.toString(longLengths));//Long Lengths: [3, 0, 2, 3, 4, 0, 3]

        // mapToDouble:转换元素为double类型
        double[] doubleLengths = strings.stream()
                .mapToDouble(String::length)//对生成的元素转换为long类型,得到DoubleStream类型的流
                .toArray();
        System.out.println("Double Lengths: " + Arrays.toString(doubleLengths));//Double Lengths: [3.0, 0.0, 2.0, 3.0, 4.0, 0.0, 3.0]

        // flatMap:将每个元素转换为另一个流,然后将这些流连接成一个流
        List<String> flatMapped = strings.stream()
                .flatMap(s -> Arrays.stream(s.split("")))//对流的每个元素拆分成新的流,s.split("")后是String[]类型
                .collect(Collectors.toList());
        System.out.println("FlatMapped: " + flatMapped);//FlatMapped: [a, b, c, , b, c, e, f, g, a, b, c, d, , j, k, l]

        // distinct:返回一个元素各不相同的新流
        List<String> distinctStrings = strings.stream()
                .distinct()//对流的元素进行去重
                .collect(Collectors.toList());
        System.out.println("Distinct: " + distinctStrings);//Distinct: [abc, , bc, efg, abcd, jkl]

        // sorted:返回一个自然排序后的流
        List<String> sortedStrings = strings.stream()
                .sorted()//对流的元素进行字典升序排序
                .collect(Collectors.toList());
        System.out.println("Sorted: " + sortedStrings);//Custom Sorted: [, , abc, abcd, bc, efg, jkl]

        // sorted(Comparator):返回一个按照指定比较器排序后的流
        List<String> customSorted = strings.stream()
                //.sorted(Comparator.reverseOrder())//对流的元素进行降序排序
                .sorted((a, b) -> b.compareTo(a))//对流的元素进行降序排序
                .collect(Collectors.toList());
        System.out.println("Custom Sorted: " + customSorted);//Custom Sorted: [jkl, efg, bc, abcd, abc, , ]

        // peek:对每个元素执行操作,并返回一个新的流
        List<String> peeked = strings.stream()
                .peek(s -> System.out.print(s + " ")) //对每个元素进行打印 abc  bc efg abcd  jkl
                .collect(Collectors.toList());
        System.out.println("\nPeeked: " + peeked);//[abc, , bc, efg, abcd, , jkl]

        // limit:截断流,使其元素不超过指定数量
        List<String> limited = strings.stream()
                .limit(3) //截取流的前面三个
                .collect(Collectors.toList());
        System.out.println("Limited: " + limited); //Limited: [abc, , bc]

        // skip:跳过前n个元素,返回剩下的元素组成的流
        List<String> skipped = strings.stream()
                .skip(3)//跳过前面三个元素
                .collect(Collectors.toList());
        System.out.println("Skipped: " + skipped); //Skipped: [efg, abcd, , jkl]
    }
}


3.  终止操作

  • forEach(Consumer action):遍历流中的每个元素,执行指定的操作。

  • forEachOrdered(Consumer action):保证forEach操作在流被并行处理时,按照原始流的顺序执行。

  • toArray():将流转换为数组。

  • reduce(T identity, BinaryOperator accumulator):通过一个起始值,反复利用BinaryOperator来处理和累积元素,返回一个值。

  • reduce(BinaryOperator accumulator):没有起始值,通过BinaryOperator处理和累积元素,返回一个Optional对象。

  • collect(Collector<T, A, R> collector):将流中的元素累积成一个结果,利用Collector进行操作。

  • min(Comparator comparator):返回流中最小元素。

  • max(Comparator comparator):返回流中最大元素。

  • count():返回流中元素的数量。

  • anyMatch(Predicate predicate):判断流中是否至少有一个元素满足条件。

  • allMatch(Predicate predicate):判断流中所有元素是否都满足条件。

  • noneMatch(Predicate predicate):判断流中是否没有元素满足条件。

  • findFirst():返回流中的第一个元素。

  • findAny():返回流中的任意一个元素,主要用于并行流。

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.Comparator;


public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

        // forEach:遍历流中的每个元素,执行指定的操作
        numbers.stream().forEach(s -> System.out.print(s + " "));//1 2 3 4 5 6 7 8 9
        System.out.println();

        // forEachOrdered:保证forEach操作在流被并行处理时,按照原始流的顺序执行
        numbers.parallelStream().forEachOrdered(s -> System.out.print(s + " "));//1 2 3 4 5 6 7 8 9
        System.out.println();

        // toArray:将流转换为数组
        Integer[] numbersArray = numbers.stream().toArray(Integer[]::new);
        //int[] array = numbers.stream().mapToInt(Integer::valueOf).toArray();
        System.out.println("Array: " + Arrays.toString(numbersArray));//Array: [1, 2, 3, 4, 5, 6, 7, 8, 9]

        // reduce(T identity, BinaryOperator accumulator):通过一个起始值,反复利用BinaryOperator来处理和累积元素,返回一个值
        int sum = numbers.stream().reduce(0, (a, b) -> a + b); //初始值sum = 0 ,(a, b) -> a + b可以改成Integer::sum
        System.out.println("Sum with identity: " + sum);//Sum with identity: 45

        // reduce(BinaryOperator accumulator):没有起始值,通过BinaryOperator处理和累积元素,返回一个Optional对象
        Optional<Integer> sumOptional = numbers.stream().reduce(Integer::sum); //Optional<Integer>类的实例可以包含一个的Integer值,也可以不包含任何值(即它是null的)。
        // System.out.println(sumOptional.orElse(null)); //该方式取值也可以,如果不存在则返回null,如果存在则取出Integer类型的值
        // Integer i = sumOptional.get(); //该方式取值也可以,要确保值存在;如果不存在会抛出异常
        sumOptional.ifPresent(s-> System.out.println(s));//45


        // collect(Collector<T, A, R> collector):将流中的元素累积成一个结果,利用Collector进行操作
        List<Integer> evenNumbers = numbers.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        System.out.println("Even numbers: " + evenNumbers); //Even numbers: [2, 4, 6, 8]

        // min(Comparator comparator):返回流中最小元素
        Optional<Integer> min = numbers.stream().min(Comparator.naturalOrder());
        min.ifPresent(System.out::println); //1

        // max(Comparator comparator):返回流中最大元素
        Optional<Integer> max = numbers.stream().max(Comparator.naturalOrder());
        max.ifPresent(System.out::println); //9

        // count():返回流中元素的数量
        long count = numbers.stream().count();
        System.out.println("Count: " + count); //Count: 9

        // anyMatch(Predicate predicate):判断流中是否至少有一个元素满足条件
        boolean anyMatch = numbers.stream().anyMatch(n -> n > 5);
        System.out.println("Any match: " + anyMatch); //Any match: true

        // allMatch(Predicate predicate):判断流中所有元素是否都满足条件
        boolean allMatch = numbers.stream().allMatch(n -> n > 0);
        System.out.println("All match: " + allMatch); //All match: true

        // noneMatch(Predicate predicate):判断流中是否没有元素满足条件
        boolean noneMatch = numbers.stream().noneMatch(n -> n < 0);//没有元素小于0
        System.out.println("None match: " + noneMatch); //None match: true

        // findFirst():返回流中的第一个元素
        Optional<Integer> first = numbers.stream().findFirst();
        first.ifPresent(System.out::println);//1

        // findAny():返回流中的任意一个元素,主要用于并行流
        Optional<Integer> any = numbers.parallelStream().findAny();
        any.ifPresent(System.out::println);//1~9任意一个数字
    }
}

五、Stream API 的练习

1. 基础练习

(1)计算整数列表的总和

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("1", "2", "3");
        //方法一
        int IntAns = list.stream()
                .mapToInt(Integer::valueOf)            //IntStream类型
                .sum();
        
        //方法二
        Integer IntegerAns = list.stream()
                .map(Integer::parseInt)                //Stream<Integer>类型
                .reduce(0, Integer::sum);              //对Stream<Integer>和IntStream类型都可以进行规约
        System.out.println("总和为:" + IntAns);        //总和为:6
        System.out.println("总和为:" + IntegerAns);    //总和为:6
    }
}

(2)找出整数列表中的最大值

import java.util.Arrays;
import java.util.List;
import java.util.OptionalInt;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);
        // 方法一
        OptionalInt max1 = list.stream()
                .mapToInt(Integer::valueOf)
                .max();
        max1.ifPresent(System.out::println); //4

        // 方法二
        int max2 = list.stream()
                .reduce(Integer.MIN_VALUE, (a, b) -> a >= b ? a : b);
        //  .reduce(Integer.MIN_VALUE, Integer::max); //初始值是第一个元素或最小值
        System.out.println(max2); //4

    }
}

(3)计算整数列表中所有偶数的平均值

import java.util.Arrays;
import java.util.List;
import java.util.OptionalDouble;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);

        //OptionalDouble是一个可能包含double数值容器,数值也有可能不存在
        OptionalDouble average = list.stream()
                .filter(n -> n % 2 == 0)
                .mapToInt(Integer::valueOf)//转换成IntStream类型
                .average();

        //ifPresent():这是OptionalDouble类中的一个方法,用于检查这个Optional对象中是否包含值。如果Optional对象包含值,那么ifPresent()方法会执行传递给它的lambda表达式。
        average.ifPresent(value -> System.out.println(value)); //3.0

    }
}

(4)筛选出一个整数列表中的偶数并打印

import java.util.Arrays;
import java.util.List;
​
public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("1", "2", "5", "3", "6");
        list.stream()
                .mapToInt(Integer::valueOf)//转换成int类型,也可以parseInt
                .filter(x -> x % 2 == 0)
                .forEach(System.out::println); 
    }
}

(5)将字符串列表中的每个元素转换为大写并收集到新的列表

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // 初始化列表
        List<String> list = Arrays.asList("aaa", "bbb", "cc", "D");

        // 将列表中的字符串转换为大写,并收集结果到新的列表中
        List<String> collect = list.stream()
                .map(String::toUpperCase) // 映射操作,将每个字符串转换为大写
                .collect(Collectors.toList()); // 收集操作,将结果收集到列表中

        // 打印转换后的列表
        System.out.println(collect); //[AAA, BBB, CC, D]
    }
}

​(6)对整数列表进行降序排序,并获取前3个元素

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        List<Integer> collect = list.stream()
                .sorted((a, b) -> b - a)
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(collect);//[8, 6, 5]

    }
}

(7)将整数列表中的每个数字乘以2,并收集到一个新的列表中

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);
        List<Integer> collect = list.stream()
                .map(s -> s * 2)
                .collect(Collectors.toList());
        collect.forEach(s -> System.out.print(s + " ")); //2 4 6 8 
    }
}

(8)检查整数列表中是否所有数字都是正数

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        boolean b = list.stream()
                .allMatch(Main::IsPositive); //对list里面的所有数进行判断
                //.allMatch(n -> n > 0); //也可以直接该写法

        System.out.println(b); //true
    }

    public static boolean IsPositive(int n) {
        return n > 0;
    }
}

(9)找出整数列表中大于5的最小值

import java.util.Arrays;
import java.util.List;
import java.util.OptionalInt;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        OptionalInt min = list.stream()
                .mapToInt(Integer::valueOf)
                .filter(n -> n > 5)
                .findFirst();
        min.ifPresent(System.out::println); //6
    }
}

(10)检查整数列表中是否存在至少一个数字大于10

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        boolean b = list.stream().anyMatch(n -> n > 5);//判断列表中是否有一个存在>5的数字
        System.out.println(b);

    }
}

(11)检查整数列表中是否包含连续的数字

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 5, 6, 7);
        boolean hasConsecutiveNumbers = list.stream()
                .anyMatch(n -> list.contains(n + 1));
        System.out.println("列表中是否包含连续的数字:" + hasConsecutiveNumbers);//列表中是否包含连续的数字:true
    }
}

(12)将整数列表中的数字进行去重

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
        List<Integer> collect = list.stream()
                .distinct()
                .collect(Collectors.toList());
        System.out.println(collect);//[3, 1, 4, 5, 9]
    }
}

(13)从字符串列表中找出最长的字符串

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("hello", "world2222", "stream22", "api", "java");
        // 方法一
        Optional<String> longestString = strings.stream().max((s1, s2) -> s1.length() - s2.length());
        longestString.ifPresent(System.out::println); //world2222

        // 方法二
        Optional<String> reduce = strings.stream().reduce((a, b) -> a.length() > b.length() ? a : b);
        System.out.println(reduce.orElse(null));//world2222
    }
}

2. 进阶练习

(14)从员工(姓名、年龄)列表中找出年龄大于30岁的员工姓名列表

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class Employee {
    private String name;
    private int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }


}

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                new Employee("Alice", 32),
                new Employee("Bob", 29),
                new Employee("Charlie", 34)
        );

        String collect = employees.stream()
                .filter(e -> e.getAge() > 30)
                .map(e -> e.getName())//对每个员工取出姓名,或直接Employee::getName
                .collect(Collectors.joining(", ")); 
        System.out.println(collect); //Alice, Charlie
    }
}

(15)计算列表中每个元素出现的次数

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> integerNumbers = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        Map<Integer, Long> collect = integerNumbers
                .stream()
                .collect(Collectors.groupingBy(e -> e, Collectors.counting()));
        //groupingBy类似与SQL中的GROUP BY
        //<e, Collectors.counting())>中,e值key,而Collectors.counting()是对每个key聚合后的值
        System.out.println(collect); // {1=1, 2=1, 3=2, 4=1, 5=1, 6=1, 8=1}
    }
}

(16)对字符串列表按单词长度进行分组,并打印出每个长度组的单词列表

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");

        Map<Integer, List<String>> wordsByLength = words.stream()
                .collect(Collectors.groupingBy(String::length)); 
        //groupingBy只有一个参数时,key就是String::length,而value就是元素本身
        
        //wordsByLength: {3=[fig], 4=[date], 5=[apple, grape], 6=[banana, cherry]}
        wordsByLength.forEach((length, wordList) -> System.out.println("Length: " + length + ", Words: " + wordList));
        
   
    }
}

(17)将整数列表中的数字分为奇数和偶数,分别存储在不同的列表中

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 4, 3, 6, 3, 8, 5);
        Map<Boolean, List<Integer>> partitionedMap = list.stream()
                .collect(Collectors.partitioningBy(n -> n % 2 == 0));
        //partitioningBy是二元分组,groupingBy是多元分组
        System.out.println("偶数列表:" + partitionedMap.get(true)); //偶数列表:[2, 4, 6, 8]
        System.out.println("奇数列表:" + partitionedMap.get(false)); //奇数列表:[1, 3, 3, 5]
    }
}

(18)将一个字符串列表中的每个字符串长度求和

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("apple", "banana", "cherry");
        // 方法一
        int totalLength1 = strings.stream()
                .collect(Collectors.summingInt(String::length));
        System.out.println(totalLength1); // 输出:17
        
        // 方法二
        int totalLength2 = strings.stream()
                .mapToInt(String::length).sum();
        System.out.println(totalLength2); // 输出:17

        // 方法三
        int totalLength3 = strings.stream()
                .reduce("",String::concat)
                .length();
        System.out.println(totalLength3); // 输出:17
    }
}

(19)对员工列表按年龄分组,并打印每个年龄组的人数

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Employee {
    String name;
    int age;

    Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return name + ": " + age;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Employee> people = Arrays.asList(
                new Employee("Alice", 22),
                new Employee("Bob", 20),
                new Employee("Charlie", 21),
                new Employee("David", 20)
        );

        //按照age进行分组,对每个分组求和
        Map<Integer, Long> peopleByAge = people.stream()
                .collect(Collectors.groupingBy(Employee::getAge, Collectors.counting()));
        peopleByAge.forEach((age, count) -> System.out.println("Age: " + age + ", Count: " + count));


        //按照age进行分组
        Map<Integer, List<Employee>> collect = people.stream()
                .collect(Collectors.groupingBy(person -> person.getAge()));
        System.out.println(collect);
        
    }
}

(20)计算字符串中每个字符出现的次数

import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        String str = "hello world";
        
        Map<Character, Long> charCountMap = str.chars() // IntStream
                .mapToObj(c -> (char) c) // Stream<Character>
                .collect(Collectors.groupingBy(c -> c, Collectors.counting()));

        System.out.println(charCountMap); //{ =1, r=1, d=1, e=1, w=1, h=1, l=3, o=2}
    }
}

(21)给定两个字符串列表,合并这两个列表,并去除重复项,然后按字母顺序排序

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("a", "b", "c");
        List<String> list2 = Arrays.asList("b", "c", "d");

        List<String> mergedList = Stream.concat(list1.stream(), list2.stream())
                .distinct()
                .sorted()
                .collect(Collectors.toList());
        System.out.println(mergedList);//[a, b, c, d]
    }
}

(22)将字符串列表转换为Map,其中键是字符串,值是字符串长度

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("apple", "banana", "cherry");

        Map<String, Integer> stringLengthMap = strings.stream()
                .collect(Collectors.toMap(s -> s, String::length));

        stringLengthMap.forEach((s, length) -> System.out.println(s + ": " + length));
//        banana: 6
//        apple: 5
//        cherry: 6
    }
}

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值