【Stream流】stream流常用操作

Stream流常用操作

1. forEach

forEach 用来遍历流中的数据。

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

// Consumer接口中的抽象方法
void accept(T t);

该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理。基本使用:

@Test
public void testForEach() {
    List<String> one = new ArrayList<>();
    Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
    // Lambda可以转成方法引用
    one.stream().forEach(System.out::println);
}

2. count

Stream流提供 count 方法来统计其中的元素个数。

long count();

该方法返回一个long值代表元素个数。基本使用:

@Test
public void testCount() {
    List<String> one = new ArrayList<>();
    Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");

    long count = one.stream().count();
    System.out.println(count);
}

3. filter

filter用于过滤数据,返回符合过滤条件的数据。

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

// Predicate接口中的抽象方法
boolean test(T t);

该接口接收一个 Predicate 函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。基本使用:

@Test
public void testFilter() {
    List<String> one = new ArrayList<>();
    Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
    // 得到名字长度为3个字的人(过滤)
    one.stream().filter(s -> s.length() == 3).forEach(System.out::println);
}

4. limit

limit 方法可以对流进行截取,只取用前n个。

Stream<T> limit(long maxSize);

参数是一个long型,如果集合当前长度大于参数则进行截取。否则不进行操作。基本使用:

@Test
public void testLimit() {
    List<String> one = new ArrayList<>();
    Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");
    // 获取前3个数据
    one.stream()
        .limit(3)
        .forEach(System.out::println);
}

5. skip

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

Stream<T> skip(long n);

如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。基本使用:

@Test
public void testSkip() {
    List<String> one = new ArrayList<>();
    Collections.addAll(one, "迪丽热巴", "宋远桥", "苏星河", "老子", "庄子", "孙子");

    // 跳过前两个数据
    one.stream()
        .skip(2)
        .forEach(System.out::println);
}

6. map

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

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

// Function 接口中抽象方法
R apply(T t);

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

@Test
public void testMap() {
    Stream<String> original = Stream.of("11", "22", "33");
    // Map可以将一种类型的流转换成另一种类型的流
    // 将Stream流中的字符串转成Integer
    // original.map(s -> Integer.parseInt(s)).forEach(System.out::println);
    original.map(Integer::parseInt).forEach(System.out::println);
}

7. sorted

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

Stream<T> sorted(); // 根据元素的自然顺序排序
Stream<T> sorted(Comparator<? super T> comparator); // 根据比较器指定的规则排序

// 其中Comparator接口中有一个抽象方法
int compare(T o1, T o2);

基本使用:

@Test
public void testSorted() {
    // sorted(): 根据元素的自然顺序排序
    // sorted(Comparator<? super T> comparator): 根据比较器指定的规则排序
    Stream<Integer> stream = Stream.of(33, 22, 11, 55);

    // stream.sorted().forEach(System.out::println);
    /*stream.sorted((Integer i1, Integer i2) -> {
            return i2 - i1;
        }).forEach(System.out::println);*/

    stream.sorted((i1, i2) -> i2 - i1).forEach(System.out::println); // 55 33 22 11
}

8. distinct

如果需要去除重复数据,可以使用 distinct 方法。方法签名:

Stream<T> distinct();

基本使用1(基本类型去重):

@Test
public void testDistinct() {
    Stream<Integer> stream = Stream.of(22, 33, 22, 11, 33);

    stream.distinct().forEach(System.out::println);

    Stream<String> stream1 = Stream.of("aa", "bb", "aa", "bb", "cc");
    stream1.distinct().forEach(System.out::println);

}

基本使用2(自定义类型去重):

@Test
public void testDistinct2() {
    Stream<Person> stream = Stream.of(
        new Person("貂蝉", 18),
        new Person("杨玉环", 20),
        new Person("杨玉环", 20),
        new Person("西施", 16),
        new Person("西施", 16),
        new Person("王昭君", 25)
    );

    stream.distinct().forEach(System.out::println);
}

注: 对于自定义的数据类型,需要重写hashCode和equals方法,否则无法进行去重。

9. match

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

boolean allMatch(Predicate<? super T> predicate); // 匹配所有元素,所有元素都需要满足条件
boolean anyMatch(Predicate<? super T> predicate); // 匹配某个元素,只要有其中一个元素满足条件即可
boolean noneMatch(Predicate<? super T> predicate); // 匹配所有元素,所有元素都不满足条件

// Predicate接口中的抽象方法
boolean test(T t);

基本使用:

@Test
public void testMatch() {
    Stream<Integer> stream = Stream.of(5, 3, 6, 1);

    // boolean b = stream.allMatch(i -> i > 0); // allMatch: 匹配所有元素,所有元素都需要满足条件
    // boolean b = stream.anyMatch(i -> i > 5); // anyMatch: 匹配某个元素,只要有其中一个元素满足条件即可
    boolean b = stream.noneMatch(i -> i < 0); // noneMatch: 匹配所有元素,所有元素都不满足条件
    System.out.println(b);
}

10. find

如果需要找到某些数据,可以使用 find 相关方法。方法签名:

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

基本使用:

@Test
public void testFind() {
    Stream<Integer> stream = Stream.of(33, 11, 22, 5);
    // Optional<Integer> first = stream.findFirst();
    Optional<Integer> first = stream.findAny();
    System.out.println(first.get());
}

11. max、min

如果需要获取最大和最小值,可以使用 max 和 min 方法。方法签名:

Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);

// Comparator接口中的抽象方法
int compare(T o1, T o2);

基本使用:

@Test
public void testMax_Min() {
    // 获取最大值
    // 1, 3, 5, 6
    Optional<Integer> max = Stream.of(5, 3, 6, 1).max((o1, o2) -> o1 - o2);
    System.out.println("最大值: " + max.get()); // 最大值: 6

    // 获取最小值
    // 1, 3, 5, 6
    Optional<Integer> min = Stream.of(5, 3, 6, 1).min((o1, o2) -> o1 - o2);
    System.out.println("最小值: " + min.get()); // 最小值: 1
}

12. reduce

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

T reduce(T identity, BinaryOperator<T> accumulator);

// 其中,BinaryOperator extends BiFunction
// BiFunction接口中有一个抽象方法
R apply(T t, U u);

基本使用:

@Test
public void testReduce() {
    // T reduce(T identity, BinaryOperator<T> accumulator);
    // T identity: 默认值
    // BinaryOperator<T> accumulator: 对数据进行处理的方式
    // reduce如何执行?
    // 第一次, 将默认值赋值给x, 取出集合第一元素赋值给y
    // 第二次, 将上一次返回的结果赋值x, 取出集合第二元素赋值给y
    // 第三次, 将上一次返回的结果赋值x, 取出集合第三元素赋值给y
    // 第四次, 将上一次返回的结果赋值x, 取出集合第四元素赋值给y
    int reduce = Stream.of(4, 5, 3, 9).reduce(0, (x, y) -> {
        System.out.println("x = " + x + ", y = " + y);
        return x + y;
    });
    System.out.println("reduce = " + reduce); // 21

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

// 输出结果:
x = 0, y = 4
x = 4, y = 5
x = 9, y = 3
x = 12, y = 9
reduce = 21
max = 9

13. map与reduce组合

基本使用

@Test
public void testMapReduce() {
    // 求出所有年龄的总和
    // 1.得到所有的年龄
    // 2.让年龄相加
    Integer totalAge = Stream.of(
        new Person("刘德华", 58),
        new Person("张学友", 56),
        new Person("郭富城", 54),
        new Person("黎明", 52))
        .map(Person::getAge).reduce(0, Integer::sum);

    System.out.println("totalAge = " + totalAge);


    // 找出最大年龄
    // 1.得到所有的年龄
    // 2.获取最大的年龄
    Integer maxAge = Stream.of(
        new Person("刘德华", 58),
        new Person("张学友", 56),
        new Person("郭富城", 54),
        new Person("黎明", 52))
        .map(Person::getAge)
        .reduce(0, Math::max);
    System.out.println("maxAge = " + maxAge);

    // 统计 a 出现的次数
    //                          1    0     0    1    0    1
    Integer count = Stream.of("a", "c", "b", "a", "b", "a")
        .map(s -> {
            if (s.equals("a")) {
                return 1;
            } else {
                return 0;
            }
        })
        .reduce(0, Integer::sum);
    System.out.println("count = " + count);
}

// 输出结果
totalAge = 220
maxAge = 58
count = 3

14. mapToInt

IntStream mapToInt(ToIntFunction<? super T> mapper);

// 其中ToIntFunction中有一个抽象方法
int applyAsInt(T value);

基本使用:

@Test
public void testNumericStream() {
    // Integer占用的内存比int多,在Stream流操作中会自动装箱和拆箱
    IntStream intStream = Stream.of(1, 2, 3, 4, 5).mapToInt(Integer::intValue);
    intStream.filter(n -> n > 3).forEach(System.out::println);
}

// 输出结果
4,5

15. concat

如果有两个流,希望合并成为一个流,那么可以使用 Stream 接口的静态方法 concat:

static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)

基本使用:

@Test
public void testContact() {
    Stream<String> streamA = Stream.of("张三");
    Stream<String> streamB = Stream.of("李四");

    // 合并成一个流
    Stream<String> newStream = Stream.concat(streamA, streamB);
    // 注意:合并流之后,不能操作之前的流啦.
    // streamA.forEach(System.out::println);

    newStream.forEach(System.out::println);
}

// 输出结果:
张三 李四
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值