【java 笔记】Stream

【java 笔记】Stream

参考于https://www.cnblogs.com/andywithu/p/7404101.html

作用

对大量数据进行集中操作的得到目标对象群

下面以一段代码为例做出解释

意为过滤掉年龄大于75的孩子

class Son{
    private String name;
    private Integer age;

    public Son(String name,Integer age){
        this.age=age;
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
public class hello {
    static Random random;
    static List<Son> sonList;
    static
    {
        random=new Random();
        sonList=new ArrayList<Son>(){
            {
                for (int i = 0; i < 100; i++) {
                    add(new Son("student" + i, random.nextInt(50) + 50));
                }
            }
        };
    }
    public static void main(String[] args){
        List<String> sons=sonList.stream()
                .filter((x)->x.getAge()>75)
                .sorted(Comparator.comparing(Son::getAge))
                .map(Son::getName)
                .collect(Collectors.toList());
        System.out.println(sons);
    }
}

通过大段stream操作输出目标流&集合&对象

目前看来作用比较简单,关键在于特性

引摘自博客的话,stream的特性主要在于三点

1.stream不存储数据

流操作是一次性的

2.stream不改变源数据

以上为例,流操作不会影响sonList中的数据

3.stream的延迟执行特性

在流的聚合操作(即常规操作)之前可以改动添加数据

操作

代码借用https://www.cnblogs.com/andywithu/p/7404101.html

/**
 * 通过数组创建流
 */
@Test
public void testArrayStream(){
    //1.通过Arrays.stream
    //1.1基本类型
    int[] arr = new int[]{1,2,34,5};
    IntStream intStream = Arrays.stream(arr);
    //1.2引用类型
    Student[] studentArr = new Student[]{new Student("s1",29),new Student("s2",27)};
    Stream<Student> studentStream = Arrays.stream(studentArr);
    //2.通过Stream.of
    Stream<Integer> stream1 = Stream.of(1,2,34,5,65);
    //注意生成的是int[]的流
    Stream<int[]> stream2 = Stream.of(arr,arr);
    stream2.forEach(System.out::println);
}

通过工具类Arrays的Stream方法将数组转化为流

/**
 * 通过集合创建流
 */
@Test
public void testCollectionStream(){
    List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
    //创建普通流
    Stream<String> stream  = strs.stream();
    //创建并行流
    Stream<String> stream1 = strs.parallelStream();
}

通过集合&表的自带的Stream方法将他们自身转化成流

@Test
public void testEmptyStream(){
    //创建一个空的stream
    Stream<Integer> stream  = Stream.empty();
}

通过Stream自身类创造空流(意义暂不明)

@Test
public void testUnlimitStream(){
    //创建无限流,通过limit提取指定大小
	Stream.generate(()->"number"+new Random()
                    .nextInt())
        			.limit(100)
        			.forEach(System.out::println);
    Stream.generate(()->new Student("name",10)).limit(20).forEach(System.out::println);
}

无限流(自动转换)

/**
 * 产生规律的数据
 */
@Test
public void testUnlimitStream1(){
    Stream.iterate(0,x->x+1).limit(10).forEach(System.out::println);
    Stream.iterate(0,x->x).limit(10).forEach(System.out::println);
    //Stream.iterate(0,x->x).limit(10).forEach(System.out::println);与如下代码意思是一样的
    Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
}

规律无限流(其中0为初始值)

public static void main(String[] args){
        long son_count=sonList.stream()
                .filter((x)->x.getAge()>75)
                .sorted(Comparator.comparing(Son::getAge))
                .distinct()
                .count();
        //System.out.println(son_count);
        Optional<Integer> LOL=Stream.iterate(20,x->x+1)
                .limit(1)
                .reduce((x,y)->x-y);
        System.out.println(LOL.get());
    }

返回Optional

流类型

原始类型流
public static void main(String[] args){
        Stream intStream=IntStream.of(4,5,6).boxed();
        intStream.forEach(System.out::println);
    }
public static void main(String[] args){
        IntStream intStream=IntStream.of(4,5,6);
        intStream.forEach(System.out::println);
    }

输出均为

4
5
6
并行流

*parallel()*方法改变流从串行流变为并行流

public static void peek1(int x) {
        System.out.println(Thread.currentThread().getName() + ":->peek1->" + x);
    }

    public static void peek2(int x) {
        System.out.println(Thread.currentThread().getName() + ":->peek2->" + x);
    }

    public static void peek3(int x) {
        System.out.println(Thread.currentThread().getName() + ":->final result->" + x);
    }

    public static void main(String[] args){
        Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10);
        stream.peek(hello::peek1).filter(x -> x > 5)
                .peek(hello::peek2).filter(x -> x < 8)
                .peek(hello::peek3)
                .forEach(System.out::println);
    }

输出为

main:->peek1->1
main:->peek1->2
main:->peek1->3
main:->peek1->4
main:->peek1->5
main:->peek1->6
main:->peek2->6
main:->final result->6
6
main:->peek1->7
main:->peek2->7
main:->final result->7
7
main:->peek1->8
main:->peek2->8
main:->peek1->9
main:->peek2->9
main:->peek1->10
main:->peek2->10

加入*parallel()*方法后

public static void main(String[] args){
        Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10).parallel();
        stream.peek(hello::peek1).filter(x -> x > 5)
                .peek(hello::peek2).filter(x -> x < 8)
                .peek(hello::peek3)
                .forEach(System.out::println);
    }

输出为

ForkJoinPool.commonPool-worker-3:->peek1->3
ForkJoinPool.commonPool-worker-1:->peek1->9
ForkJoinPool.commonPool-worker-1:->peek2->9
ForkJoinPool.commonPool-worker-1:->peek1->10
ForkJoinPool.commonPool-worker-1:->peek2->10
ForkJoinPool.commonPool-worker-4:->peek1->5
ForkJoinPool.commonPool-worker-2:->peek1->2
ForkJoinPool.commonPool-worker-5:->peek1->1
main:->peek1->7
main:->peek2->7
main:->final result->7
7
ForkJoinPool.commonPool-worker-1:->peek1->4
ForkJoinPool.commonPool-worker-6:->peek1->6
ForkJoinPool.commonPool-worker-3:->peek1->8
ForkJoinPool.commonPool-worker-6:->peek2->6
ForkJoinPool.commonPool-worker-3:->peek2->8
ForkJoinPool.commonPool-worker-6:->final result->6
6

可以看出加入*parallel()*方法明显数据处理以并行方式进行

以下文字摘自https://www.cnblogs.com/andywithu/p/7404101.html

我们将stream.filter(x -> x > 5).filter(x -> x < 8).forEach(System.out::println)的过程想象成上图的管道,我们在管道上加入的peek相当于一个阀门,透过这个阀门查看流经的数据,

1)当我们使用顺序流时,数据按照源数据的顺序依次通过管道,当一个数据被filter过滤,或者经过整个管道而输出后,第二个数据才会开始重复这一过程

2)当我们使用并行流时,系统除了主线程外启动了七个线程(我的电脑是4核八线程)来执行处理任务,因此执行是无序的,但同一个线程内处理的数据是按顺序进行的。

sorted()、distinct()等对并行流的影响

sorted()、distinct()是元素相关方法,和整体的数据是有关系的,map,filter等方法和已经通过的元素是不相关的,不需要知道流里面有哪些元素 ,并行执行和sorted会不会产生冲突呢?

结论:

1.并行流和排序是不冲突的

2.一个流是否是有序的,对于一些api可能会提高执行效率,对于另一些api可能会降低执行效率

3.如果想要输出的结果是有序的,对于并行的流需要使用forEachOrdered(forEach的输出效率更高)

在积累了一点知识后,我们下一章将从新开始学习设计思想Abstract-document

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值