栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java8新特性——Stream流

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java8新特性——Stream流

Java8新特性——Stream流
  • 一、Stream流简介
    • 1.1 什么是Stream流?
    • 1.2 为什么使用Stream流?
    • 1.3 Stream流的特性
  • 二、创建Stream流
    • 2.1 通过 Collection 扩展接口创建流
    • 2.2 由数组创建流
    • 2.3 由值创建流
    • 2.4 由函数创建流
  • 三、Stream流的中间操作
    • 3.1 筛选与切片
    • 3.2 映射
    • 3.3 排序
  • 四、Stream流的终止操作
    • 4.1 查找与匹配
    • 4.2 归约
    • 4.3 收集

一、Stream流简介 1.1 什么是Stream流?

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

———摘自菜鸟教程

流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
集合讲的是数据,流讲的是计算!

1.2 为什么使用Stream流?

Stream流可以对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。Stream API 借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。

1.3 Stream流的特性
  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
二、创建Stream流

一个数据源(如:集合、数组),获取一个流。

2.1 通过 Collection 扩展接口创建流

Collection 接口被扩展,提供了两个获取流的方法。

default Stream stream() : 返回一个顺序流
default Stream parallelStream() : 返回一个并行流

List list = Arrays.asList("1", "2", "3", "zs", "abc");
Stream stream1 = list.stream();
Stream stream2 = list.parallelStream();
2.2 由数组创建流

Arrays 的静态方法 stream() 可以获取数组流。

static Stream stream(T[] array): 返回一个流

IntStream intStream = Arrays.stream(new int[]{1, 2, 3});
LongStream longStream = Arrays.stream(new long[]{123L, 46L});
DoubleStream doubleStream = Arrays.stream(new double[]{12.3, 34.56});
2.3 由值创建流

可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。

public static Stream of(T... values) : 返回一个流

Stream streamValue = Stream.of("a", "b", "c");
2.4 由函数创建流

可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。

迭代 public static Stream iterate(final T seed, final UnaryOperator f)
生成 public static Stream generate(Supplier s)

//迭代(需要传入一个种子,也就是起始值,然后传入一个一元操作)
Stream integerStream = Stream.iterate(2, (x) -> x * 2);
//生成(无限产生对象)
Stream doubleStream = Stream.generate(() -> Math.random());
三、Stream流的中间操作

一个中间操作链,对数据源的数据进行处理。

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

3.1 筛选与切片
方法描述
filter(Predicate p)接收 Lambda , 从流中排除某些元素。
distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
limit(long maxSize)截断流,使其元素不超过给定数量。
skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
// 1、匿名内部类的方式
Stream filterStream1 = userEntities.stream();
filterStream1.filter(new Predicate() {
    @Override
    public boolean test(UserEntity userEntity) {
        return userEntity.getAge() >= 35;
    }
}).filter(new Predicate() {
    @Override
    public boolean test(UserEntity userEntity) {
        return userEntity.getName().equals("zhangsan");
    }
}).forEach(new Consumer() {
    @Override
    public void accept(UserEntity userEntity) {
        System.out.println("匿名内部类的方式进行过滤:" + userEntity.toString());
    }
});
// 2、lambda的方式 相关条件可以使用&&符合拼接,也可以再次使用filter
Stream filterStream2 = userEntities.stream();
filterStream2.filter(userEntity -> userEntity.getAge() >= 35 && userEntity.getName().equals("zhangsan"))
        .forEach(userEntity -> System.out.println("lambda的方式进行过滤:" + userEntity.toString()));



// limit就是从头开始获取
// skip就是表示跳过
Stream limitStream = userEntities.stream();
limitStream.skip(2).limit(1).forEach(userEntity -> System.out.println("使用skip和limit:" + userEntity));
3.2 映射
方法描述
map(Function f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 DoubleStream。
mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 LongStream。
flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
List userList = Arrays.asList(new UserEntity("a",1),new UserEntity("ab",3),new UserEntity("c",11),new SUserEntityu("f",12));
Stream stream = userList .stream();
// 去除list中所有的年龄
stream.map(UserEntity::getAge).forEach(System.out::println);
// 把所有年龄再返回一个集合
List collect = stream.map(UserEntity::getAge).collect(Collectors.toList());
stream.flatMap(userEntity-> test1.filterCharacter(userEntity.getName())).forEach(System.out::println);
3.3 排序
方法描述
sorted()产生一个新流,其中按自然顺序排序
sorted(Comparator comp)产生一个新流,其中按比较器顺序排序
// 1、匿名内部类的方式
Stream sortedStream1 = userEntities.stream();
sortedStream1.sorted(new Comparator() {
    @Override
    public int compare(UserEntity o1, UserEntity o2) {
        // 升序
        return o1.getAge() - o2.getAge();
    }
}).forEach(new Consumer() {
    @Override
    public void accept(UserEntity userEntity) {
        System.out.println("使用匿名内部类的方式排序:" + userEntity.toString());
    }
});
// 2、lambda的方式
Stream sortedStream2 = userEntities.stream();
sortedStream2.sorted((o1, o2) -> o1.getAge() - o2.getAge())
        .forEach(userEntity -> System.out.println("使用lambda的方式排序:" + userEntity.toString()));
四、Stream流的终止操作

一个终止操作,执行中间操作链,并产生结果。

4.1 查找与匹配
方法描述
allMatch(Predicate p)检查是否匹配所有元素
anyMatch(Predicate p)检查是否至少匹配一个元素
noneMatch(Predicate p)检查是否没有匹配所有元素
findFirst()返回第一个元素
findAny()返回当前流中的任意元素
count()返回流中元素总数
max(Comparator c)返回流中最大值
min(Comparator c)返回流中最小值
forEach(Consumer c)内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做了)
// 1、匿名内部类的方式
Stream noneMatch1 = userEntities.stream();
boolean result = noneMatch1.noneMatch(new Predicate() {
    @Override
    public boolean test(UserEntity userEntity) {
        return userEntity.getAge() > 32;
    }
});
System.out.println("noneMatch使用匿名内部类的方式:" + result);
// 2、lambda的方式
Stream noneMatch2 = userEntities.stream();
boolean result2 = noneMatch2.noneMatch((user) -> user.getAge() > 35);
System.out.println("noneMatch使用lambda的方式:" + result2);

// 1、匿名内部类的方式
Stream allMatch1 = userEntities.stream();
boolean result3 = allMatch1.allMatch(new Predicate() {
    @Override
    public boolean test(UserEntity userEntity) {
        return userEntity.getAge() < 54;
    }
});
System.out.println("allMatch使用匿名内部类的方式:" + result3);
// 2、lambda的方式
Stream allMatch2 = userEntities.stream();
boolean result4 = allMatch2.allMatch((user) -> user.getAge() <54);
System.out.println("allMatch使用lambda的方式:" + result4);

// 1、匿名内部类的方式
Stream anyMatch1 = userEntities.stream();
boolean result5 = anyMatch1.anyMatch(new Predicate() {
    @Override
    public boolean test(UserEntity userEntity) {
        return userEntity.getAge() > 20;
    }
});
System.out.println("anyMatch使用匿名内部类的方式:" + result5);
// 2、lambda的方式
Stream anyMatch2 = userEntities.stream();
boolean result6 = anyMatch2.anyMatch((user) -> user.getAge() > 20);
System.out.println("anyMatch使用lambda的方式:" + result6);
4.2 归约
方法描述
reduce(T iden, BinaryOperator b)可以将流中元素反复结合起来,得到一个值。 返回 T
reduce(BinaryOperator b)可以将流中元素反复结合起来,得到一个值。返回 Optional< T >
// 1、使用匿名内部类的方式
Stream integerStream1 = Stream.of(10, 30, 80, 60, 10, 70);
Optional reduce = integerStream1.reduce(new BinaryOperator() {
    @Override
    public Integer apply(Integer integer, Integer integer2) {
        return integer + integer2;
    }
});
System.out.println(reduce.get());
// 2、使用lambda的方式
Stream integerStream2 = Stream.of(10, 30, 80, 60, 10, 70);
Optional reduce2 = integerStream2.reduce((a1, a2) -> a1 + a2);
System.out.println(reduce2.get());




// 1、使用匿名内部类的方式
Stream objStream1 = userEntities.stream();
Optional reduce3 = objStream1.reduce(new BinaryOperator() {
    @Override
    public UserEntity apply(UserEntity userEntity, UserEntity userEntity2) {
        userEntity.setAge(userEntity.getAge() + userEntity2.getAge());
        return userEntity;
    }
});
System.out.println(reduce3.get().getAge());
// 2、使用lambda的方式
Stream objStream2 = userEntities.stream();
Optional reduce4 = objStream2.reduce((user1, user2) -> {
    user1.setAge(user1.getAge() + user2.getAge());
    return user1;
});
System.out.println(reduce4.get().getAge());
4.3 收集
方法描述
collect(Collector c)将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下:

方法返回类型描述
toListList< T >把流中元素收集到List
toSetSet< T >把流中元素收集到Set
toCollectionCollection< T >把流中元素收集到创建的集合
countingLong计算流中元素的个数
summingIntInteger对流中元素的整数属性求和
averagingIntDouble计算流中元素Integer属性的平均值
summarizingIntIntSummaryStatistics收集流中Integer属性的统计值。 如:平均值
joiningString连接流中每个字符串
maxByOptional< T >根据比较器选择最大值
minByOptional< T >根据比较器选择最小值
reducing归约产生的类型从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
collectingAndThen转换函数返回的类型包裹另一个收集器,对其结果转换函数
groupingByMap>根据某属性值对流分组,属性为K,结果为V
partitioningByMap>根据true或false进行分区
Stream stream1 = userEntities.stream();
Set collectSet = stream1.collect(Collectors.toSet());
System.out.println(collectSet);



Stream stream2 = userEntities.stream();
Map collectMap = stream2.collect(Collectors.toMap(
        // String对应map中的key
        new Function() {
            @Override
            public String apply(UserEntity userEntity) {
                return userEntity.getName();
            }
        },
        // UserEntity对应map中的value
        new Function() {
            @Override
            public UserEntity apply(UserEntity userEntity) {
                return userEntity;
            }
        }));
// 遍历将键值输出
collectMap.forEach(new BiConsumer() {
    @Override
    public void accept(String s, UserEntity userEntity) {
        System.out.println("s:" + s + ",:" + userEntity.toString());
    }
});
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/582058.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号