Java8之Stream(1)

Java8出来有一年多的时间了,在最开始出来的时候,我只是简单的看了一下他的文档,并且看了一下其中的一些例子,并没有将自己的日常开发切换到Java8中,最近的项目开发中,公司要求将JDK的平台升级到Java8中,因此我觉得有必要逐渐梳理一下Java8中的一些新的特性,Java8其实在Java的发展过程中绝对是里程碑式的存在,有很多很多新颖的编程方式,可以这么说吧,Lambda的出现改变了Java的编程方式,使这门语法紧凑的纯纯面向对象的语言,开始兼容函数式编程的风格,我不想评价是不是进步(因为面向函数的语言其实已经很多了,并且很流行),但是最起码Java平台做出来改变,我更想说是一种演进和演变。

我们来一起学习一下Java8的新特性Stream,其中可能需要你具备一些Lambda的知识,一些Collections的知识,然后我们就快速上手吧,其中为了说明并行计算,我可能会介绍一下JDK7中的Fork Join和快速排序算法等。

一、Stream简单介绍

Stream是Java8中比较闪亮的一个新特性,但是它绝对不等同于IO包中的Stream和解析XML的Stream,JAVA  8中的Stream也不是一个容器,它绝对不是用来存储数据的,他是对JDK中Collections的一个增强,他只专注于对集合对象的便利,高效的聚合操作,它不仅支持串行的操作功能,而且还借助JDK1.7 中的Fork-Join机制支持了并行模式,你无需编写任何一行并行相关的代码,就能高效方便的写出高并发的程序,尤其在现在多核CPU的时代,最大程度的利用CPU的超快计算能力显得尤为重要。

二、Stream之Hello World

在开始介绍Stream的各个使用细节的时候,我们先来快速看一个入门的示例,先有一个简单的认识,为了能够体现出来Stream的便捷,我们同样的需求,分别使用传统的方式和Stream的方式各实现一次。

2.1 需求描述

在一个水果的集合中,获取苹果这一个单品并且以价格降序的方式形成一个新的集合,这个新的集合中只存放价格,也就是List<Integer>,虽然这个例子在实际中有些扯淡,但是我们为了简单演示一下如何使用Stream,所以重点关注用法,不用理会需求的严谨与否。

2.2 代码实现

Fruit类,代码如下:

package com.wangwenjun.stream;

/**

 * Created by wangwenjun on 2015/8/8.

 */

public class Fruit {

    private final String name;

    private final double price;

    public Fruit(String name, double price) {

        this.name = name;

        this.price = price;

    }

    public String getName() {

        return name;

    }

    public double getPrice() {

        return price;

    }

}

FruitSelector类,代码如下

package com.wangwenjun.stream;

import java.util.ArrayList;

import java.util.List;

/**

 * Created by wangwenjun on 2015/8/8.

 */

public abstract class FruitSelector {

    protected final static String CANDIDATE_FRUIT = "apple";

    private List<Fruit> getData(){

        final List<Fruit> data = new ArrayList<Fruit>(){

            {

                add(new Fruit("apple",22.1));

                add(new Fruit("apple",22.2));

                add(new Fruit("apple",22.3));

                add(new Fruit("apple",22.4));

                add(new Fruit("apple",22.5));

                add(new Fruit("apple",22.6));

                add(new Fruit("apple",22.7));

                add(new Fruit("orange",22.8));

                add(new Fruit("orange",22.9));

                add(new Fruit("orange",23.0));

                add(new Fruit("orange",23.1));

                add(new Fruit("orange",24.2));

                add(new Fruit("orange",22.3));

                add(new Fruit("banana",22.4));

                add(new Fruit("banana",22.2));

                add(new Fruit("banana",22.2));

                add(new Fruit("banana",22.2));

                add(new Fruit("banana",22.2));

            }

        };

        return data;

    }

    public List<Double> select()

    {

        List<Fruit> fruits= getData();

        return doFilter(fruits);

    }

    protected abstract List<Double> doFilter(final List<Fruit> fruits);

}

IteratorFruitSelector类代码如下,他是使用我们传统迭代的方式去做这样的工作。

package com.wangwenjun.stream;

import java.util.*;

public class IteratorFruitSelector extends FruitSelector {

    @Override

    protected List<Double> doFilter(List<Fruit> fruits) {

        //get the fruit name is 'apple'

        List<Fruit> appleList = new ArrayList<>();

        Iterator<Fruit> iterator = fruits.iterator();

        for (; iterator.hasNext(); ) {

            Fruit fruit = iterator.next();

            if (fruit.getName().equals(CANDIDATE_FRUIT)) {

                appleList.add(fruit);

            }

        }

        //do sort.

        Collections.sort(appleList, (o1, o2) -> {

            if (o1.getPrice() > o2.getPrice()) return 1;

            else if (o1.getPrice() == o2.getPrice()) return 0;

            else return -1;

        });

        //do filter.

        List<Double> applePriceList = new ArrayList<>();

        for (Fruit fruit : appleList) {

            applePriceList.add(fruit.getPrice());

        }

        return applePriceList;

    }

}

我们使用Stream的方式看看,代码如何去写呢?

package com.wangwenjun.stream;

import java.util.Comparator;

import java.util.List;

import static java.util.stream.Collectors.toList;

/**

 * Created by wangwenjun on 2015/8/8.

 */

public class StreamFruitSelector extends FruitSelector {

    @Override

    protected List<Double> doFilter(List<Fruit> fruits) {

        return fruits.stream().filter(f -> f.getName().equals(CANDIDATE_FRUIT))

                .sorted(Comparator.comparing(Fruit::getPrice))

                .map(Fruit::getPrice)

                .collect(toList());

    }

}

代码写完了,简单对照一下,你是不是能看出来,采用Stream的方式比传统的方式要简洁很多很多,代码量至少少了2/3.

2.3 简单测试

好了,我们写一下单元测试,看看是不是两者运行情况一样呢?当然我们并没有测试性能的意思,如果你想测试性能,可以把数据量改到很大,并且Stream采用并行的工作模式,差异还是蛮多的。

package com.wangwenjun.stream;

import org.junit.Test;

import java.util.List;

/**

 * Created by wangwenjun on 2015/8/8.

 */

public class FruitSelectorTest

{

    @Test

    public void testIterator()

    {

        FruitSelector selector = new IteratorFruitSelector();

        List<Double> result = selector.select();

        System.out.println(result);

    }

    @Test

    public void testStream()

    {

        FruitSelector selector = new StreamFruitSelector();

        List<Double> result = selector.select();

        System.out.println(result);

    }

}

运行结果不言而喻了吧

[22.1, 22.2, 22.3, 22.4, 22.5, 22.6, 22.7]

[22.1, 22.2, 22.3, 22.4, 22.5, 22.6, 22.7]


完整文档下载地址在: http://download.csdn.net/detail/wangwenjun69/8981633

猜你喜欢

转载自blog.csdn.net/wangwenjun69/article/details/47400667