跳至主要內容

常用方法

Mr.Hope...大约 6 分钟

方法名方法作用返回值类型方法种类
count统计个数long终结
forEach逐一处理void终结
filter过滤Stream非终结
limit取用前几个Stream非终结
skip跳过前几个Stream非终结
map映射Stream非终结
concat组合Stream非终结

"终结"方法指的是返回值类型不再是 Stream 类型的方法,它们不支持链式调用。

"非终结"方法指的是返回值类型仍然是 Stream 类型的方法,它们支持链式调用。

注意

  1. Stream只能操作一次
  2. Stream方法返回的是新的流
  3. Stream不调用终结方法,中间的操作不会执行

1. forEach

forEach 用来遍历流中的数据的

void forEach(Consumer<? super T> action);

该方法接受一个 Consumer 接口,会将每一个流元素交给函数处理

public static void main(String[] args) {
    Stream.of("a1", "a2", "a3").forEach(System.out::println);;
}

2. count

Stream流中的 count 方法用来统计其中的元素个数的

long count();

该方法返回一个 long 值,代表元素的个数。

public static void main(String[] args) {
    long count = Stream.of("a1", "a2", "a3").count();
    System.out.println(count);
}

3. filter

filter 方法的作用是用来过滤数据的。返回符合条件的数据

可以通过 filter 方法将一个流转换成另一个子集流

Stream<T> filter(Predicate<? super T> predicate);

该接口接收一个 Predicate 函数式接口参数作为筛选条件

javaCopy codepublic static void main(String[] args) {
    Stream.of("a1", "a2", "a3","bb","cc","aa","dd")
            .filter((s)->s.contains("a"))
            .forEach(System.out::println);
}

Output:

a2
a3
aa

4.limit

image-20240415092954702

limit方法可以对流进行截取处理,支取前n个数据

 Stream<T> limit(long maxSize);

参数是一个long类型的数值,如果集合当前长度大于参数就进行截取,否则不操作

Stream<T> limit(long maxSize);
javaCopy codepublic static void main(String[] args) {
    Stream.of("a1", "a2", "a3","bb","cc","aa","dd")
            .limit(3)
            .forEach(System.out::println);
}

Output:

a1
a2
a3

5. skip

image-20240415093107540

如果希望跳过前面几个元素,可以使用 skip 方法获取一个截取之后的新流:

Stream<T> skip(long n);

操作:

javaCopy codepublic static void main(String[] args) {
    Stream.of("a1", "a2", "a3","bb","cc","aa","dd")
            .skip(3)
            .forEach(System.out::println);
}

Output:

bb
cc
aa
dd

6. map

如果我们需要将流中的元素映射到另一个流中,可以使用 map 方法:

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

提示

? 是通配符,表示任意类型。在 Function<? super T, ? extends R> 中,? super T 表示接受 TT 的超类作为参数,? extends R 表示返回 RR 的子类

该接口需要一个 Function 函数式接口参数,可以将当前流中的 T 类型数据转换为另一种 R 类型的数据

javaCopy codepublic static void main(String[] args) {
    Stream.of("1", "2", "3","4","5","6","7")
            .map(Integer::parseInt)
            .forEach(System.out::println);
}

7. sorted

如果需要将数据排序,可以使用 sorted 方法:

Stream<T> sorted();

在使用的时候可以根据自然规则排序,也可以通过比较强来指定对应的排序规则

javaCopy codepublic static void main(String[] args) {
    Stream.of("1", "3", "2","4","0","9","7")
    .map(Integer::parseInt)
    //.sorted() // 根据数据的自然顺序排序
    .sorted((o1,o2)->o2-o1) // 根据比较强指定排序规则
    .forEach(System.out::println);
}

8. distinct

image-20240415093714493

如果要去掉重复数据,可以使用 distinct 方法:

Stream<T> distinct();

Stream流中的distinct方法对于基本数据类型是可以直接去重的,但是对于自定义类型,我们是需要重写 hashCodeequals 方法来移除重复元素。

public static void main(String[] args) {
    Stream.of("1", "3", "3","4","0","1","7")
            .map(Integer::parseInt)
            //.sorted() // 根据数据的自然顺序排序
            .sorted((o1,o2)->o2-o1) // 根据比较强指定排序规则
            .distinct() // 去掉重复的记录
            .forEach(System.out::println);
    System.out.println("--------");
    Stream.of(
            new Person("张三",18)
            ,new Person("李四",22)
            ,new Person("张三",18)
    ).distinct()
            .forEach(System.out::println);
}

9. match

如果需要判断数据是否匹配指定的条件,可以使用 match 相关的方法

使用

boolean anyMatch(Predicate<? super T> predicate); // 元素是否有任意一个满足条件
boolean allMatch(Predicate<? super T> predicate); // 元素是否都满足条件
boolean noneMatch(Predicate<? super T> predicate); // 元素是否都不满足条件

注意: match 是一个终结方法

public static void main(String[] args) {
    boolean b = Stream.of("1", "3", "3", "4", "5", "1", "7")
            .map(Integer::parseInt)
            //.allMatch(s -> s > 0)
            //.anyMatch(s -> s >4)
            .noneMatch(s -> s > 4);
    System.out.println(b);
}

10. find

image-20240415094149084

如果我们需要找到某些数据,可以使用 find 方法来实现

Optional<T> findFirst();
Optional<T> findAny();

使用:

public static void main(String[] args) {
    Optional<String> first = Stream.of("1", "3", "3", "4", "5", "1", "7").findFirst();
    System.out.println(first.get());
    Optional<String> any = Stream.of("1", "3", "3", "4", "5", "1", "7").findAny();
    System.out.println(any.get());
}

11. max和min

如果我们想要获取最大值和最小值,那么可以使用 maxmin 方法

Optional<T> min(Comparator<? super T> comparator);
Optional<T> max(Comparator<? super T> comparator);
public static void main(String[] args) {
    //max
    Optional<Integer> max = Stream.of("1", "3", "3", "4", "5", "1", "7")
            .map(Integer::parseInt)
            .max((o1,o2)->o1-o2);
    System.out.println(max.get());
    //min
    Optional<Integer> min = Stream.of("1", "3", "3", "4", "5", "1", "7")
        .map(Integer::parseInt)
        .min((o1,o2)->o1-o2);
	System.out.println(min.get());
    
}

12. reduce

image-20240415094738606

如果需要将所有数据归纳得到一个数据,可以使用 reduce 方法

T reduce(T identity, BinaryOperator<T> accumulator);
public static void main(String[] args) {
    Integer sum = Stream.of(4, 5, 3, 9)
            // identity默认值
            // 第一次的时候会将默认值赋值给x
            // 之后每次会将上一次的操作结果赋值给x,y就是每次从数据中获取的元素
            .reduce(0, (x, y) -> {
                System.out.println("x="+x+",y="+y);
                return x + y;
            });
    System.out.println(sum);

    // 获取最大值
    Integer max = Stream.of(4, 5, 3, 9)
            .reduce(0, (x, y) -> {
                return x > y ? x : y;
            });
    System.out.println(max);
}

Output:

x=0,y=4
x=4,y=5
x=9,y=3
x=12,y=9
21
9//最大值

13.map和reduce的组合

在实际开发中我们经常会将map和reduce一块来使用

public static void main(String[] args) {
        Integer sumAge = Stream.of(
                        new Person("张三", 18)
                        , new Person("李四", 22)
                        , new Person("张三", 13)
                        , new Person("王五", 15)
                        , new Person("张三", 19)
                ).map(Person::getAge)
                .reduce(0, Integer::sum);
        System.out.println(sumAge);

        Integer maxAge = Stream.of(
                        new Person("张三", 18)
                        , new Person("李四", 22)
                        , new Person("张三", 13)
                        , new Person("王五", 15)
                        , new Person("张三", 19)
                ).map(Person::getAge)
                .reduce(0, Math::max);
        System.out.println(maxAge);
        //有多少个'a'
        Integer count = Stream.of("a", "b", "c", "d", "a", "c", "a")
                .map(ch -> "a".equals(ch) ? 1 : 0)
                .reduce(0, Integer::sum);
        System.out.println(count);
    }

Output:

87
22
3

14. mapToInt

如果需要将Stream中的Integer类型转换成int类型,可以使用mapToInt方法来实现

image-20240415100419114
public static void main(String[] args) {
    // Integer占用的内存比int多很多,在Stream流操作中会自动装修和拆箱操作
    Integer[] arr = {1,2,3,5,6,8};
    Stream.of(arr)
            .filter(i->i>0)
            .forEach(System.out::println);
    System.out.println("---------");
    // 为了提高程序代码的效率,我们可以先将流中Integer数据转换为int数据,然后再操作
    IntStream intStream = Stream.of(arr)
            .mapToInt(Integer::intValue);
    intStream.filter(i->i>3)
            .forEach(System.out::println);
}

15. concat

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) {
    Stream<String> stream1 = Stream.of("a","b","c");
    Stream<String> stream2 = Stream.of("x", "y", "z");
    // 通过concat方法将两个流合并为一个新的流
    Stream.concat(stream1,stream2).forEach(System.out::println);
}