Java8新特性(二)—— Stream的使用

举报
写博客发家致富_ 发表于 2021/08/17 14:37:37 2021/08/17
【摘要】 Stream是java8推出的另一强大功能,使用函数式编程的理念,让开发者专注于数据逻辑处理上,不需要过多关心对象的创建等。

一、什么是Stream

类似Iterator,可以对一个集合中的各个元素进行遍历,并执行某些操作。但与Iterator不同的是,首先Stream不需要显示的对每个元素逐个进行处理,只需指定要执行的操作例如“获取每个字符串的首字母”、“过滤掉长度大于10的字符串”,Stream会隐式的对元素进行遍历筛选,最后在需要的时候返回结果。其次相比于Iterator的串行操作而言,Stream支持并行化操作,不需要每个元素读完再读取下一个,而可以将数据分成多段,每一段在不同的线程中处理,然后将结果一起输出。

二、Stream的特点及操作分类

1)Stream的特点

  • Stream不是数据结构,不会保存数据。Stream中的数据只能遍历处理一次,遍历过一次就用尽了。
  • Stream不会修改原来数据流中的数据,每次操作完之后会生成新的Stream对象。
  • Stream的操作是懒执行的,只有最终结果需要的时候才执行。

2)Stream的操作分类:

Stream的操作可以分为中间操作(Intermediate operations)、终端操作(Terminal operations)两种操作,其中中间操作又可以分为无状态和有状态操作,终端操作又可以分为非短路操作和短路操作。

Stream操作分类

中间操作

Intermediate operations

无状态

unordered()、filter()、map()、mapToInt()、mapToLong()、

mapToDouble()、flatMap()、flatMapToInt()、flatMapToLong()

flatMapToDouble()、peek()

有状态

distinct()、sorted()、limit()、skip()

终端操作

Terminal operations

非短路操作

forEach()、forEachOrdered()、toArray()、reduce()、collect()、

max()、min()、count()

短路操作

anyMatch()、allMatch()、noneMatch()、findFirst()、findAny()

  • 中间操作:中间操作是指操作期间只是对操作进行了记录,结束操作时才会触发实际的计算。
    • 无状态操作:元素的处理不受之前元素的影响。
    • 有状态操作:该操作只有拿到所有元素之后才可以继续执行。
  • 终端操作:一个Stream对象只能有一个终端操作,指最后需要真实处理数据的操作,一旦发生,就会生成对应的处理结果。
    • 非短路操作:指必须处理完所有元素才能得到最终结果。
    • 短路操作:指遇到某些符合条件的元素就可以得到最终结果。

三、Stream的创建方式

1)使用of方法:用于为给给定元素创建顺序留,可以传递单个元素或多个元素,元素类型可以为基本数据类型也可以为其他类型

1:创建字符串流

public class StreamExercise {
   
static Stream<String> stream = Stream.of("Red","Blue","Green");

    public static void
main(String[] args) {
       
stream.forEach(System.out::println);

   
}
}

执行结果:

2:创建对象流

public class StreamExercise {

    public static void main(String[] args) {

        Stream<User> userStream = Stream.of(

            new User("Aaron", 22),

            new User("Alice", 20),

            new User("Amy", 25)

        );

        userStream.forEach(u -> System.out.println(u.getUserName()));

    }

}



class User {

    private String userName;

    private int age;

    public User(String userName, int age) {

        this.userName = userName;

        this.age = age;

    }

    public String getUserName() {

        return userName;

    }

    public void setUserName(String userName) {

        this.userName = userName;

    }

} 

3:创建IntDoubleLong的流,需要使用IntStream.of/DoubleStream.of/LongStream.of方法

public class StreamExercise {

    public static void main(String[] args) {

        System.out.println("--- IntStream ---");

        IntStream intStream = IntStream.of(1, 2, 3);

        intStream.forEach(System.out::println);



        System.out.println("--- LongStream ---");

        LongStream longStream = LongStream.of(100L, 200L, 300L);

        longStream.forEach(System.out::println);



        System.out.println("--- DoubleStream ---");

        DoubleStream doubleStream = DoubleStream.of(123.45, 456.78, 789.12);

        doubleStream.forEach(System.out::println);

    }

}
  • 使用集合和数组自带的stream( )方法创建流

例:

public class StreamExercise {

    public static void main(String[] args) {

        //String类型

        String[] characters = {"Java8", "In", "Action"};

        Stream<String> stream1 = Arrays.stream(characters);

        stream1.forEach(System.out::println);

        //Integer类型

        Integer[] numbers = {1, 3, 5, 7, 9};

        Stream<Integer> stream2 = Arrays.stream(numbers);

        stream2.forEach(System.out::println);

    }

}
public class StreamExercise {

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();

        list.add("Java");

        list.add("python");

        list.add("c++");

        list.add("c");

        list.add("sql");



        Stream<String> listStream = list.stream();

        listStream.forEach(System.out::println);

    }

}
  • 使用generate( )Stream.iterate( )方法创建无限流

1generate( )方法接受一个参数函数

public class StreamExercise {

    public static void main(String[] args) {

        Stream.generate(Math::random)

            .limit(5)

            .forEach(System.out::println);

    }

}

执行结果:

 

2iterate( )方法接受一个初始值,还有一个应用在每个新生成的数值上的函数

public class StreamExercise {

    public static void main(String[] args) {

        Stream.iterate(0, n -> n + 2)

            .limit(10)

            .forEach(System.out::println);

    }

}

执行结果:

 

四、Stream常用方法举例

中间无状态操作:

  • filter( ): 筛选出符合条件的元素

例:

public class StreamExercise {

    public static void main(String[] args) {

        Stream.iterate(0, n -> n + 2)

            .limit(10)

            .filter(i -> i > 5)

            .forEach(System.out::println);

    }

}

结果:

  • map( ): 对一个流中的值进行某种转换。需要传递一个转换的函数作为参数

例:

public class StreamExercise {

    public static void main(String[] args) {

        Stream.iterate(0, n -> n + 2)

            .limit(10)

            .map(i -> i / 2)

            .forEach(System.out::println);

    }

}

结果:

  • flatmap( ): 使用一个函数作为参数,将流中的每个值替换为另一个流,然后把所有流连接成一个流。
public class StreamExercise {

    public static void main(String[] args) {

        Stream<String> flatMapStreamObj = Stream.of("a,b,c", "a,e,f", "g,h,i");

        flatMapStreamObj.flatMap(str -> {

            String[] arr = str.split(",");

            return Arrays.stream(arr);

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

    }

}

结果:

中间有状态操作:

  • limit(n)skip(n)方法:limit方法返回一个包含n个元素的新的流;skip方法返回一个丢弃前面n个元素的新的流。使用方法上面例子中已经包含了,在此不额外举例。
  • distinct( ):根据原始流中的元素返回一个具有相同顺序、去除了重复数据的流。该方法使用较简单,在此不举例。
  • sorted( ):返回排序后的流

例:

public class StreamExercise {

    public static void main(String[] args) {

        Stream<String> flatMapStreamObj = Stream.of("a,b,c", "a,e,f", "g,h,i");

        flatMapStreamObj.sorted().forEach(System.out::println);

    }

}

结果:

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。