Java8 Stream简单的应用

  • Post author:
  • Post category:java




流的简介


简短的定义:从支持数据处理操作的源生成的元素序列


剖析这个定义


元素序列:像集合一样,流也提供了一个接口,可以访问特定元素类型的一组有序值,因为集合是数据结构,所以他的主要目的是以特定的时间/空间复杂度存储和访问元素,但流的目的在于表达计算。集合讲的是数据,流讲的是计算。


源:流会使用一个提供数据的源,如集合、数组或输入/输出资源。请注意,从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素序列与列表一致。


数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如filter、map、reduce、find、match、sort等。流操作可以顺序执行也可以并发执行。


流水线:很多流操作本身会返回一个流,这样多个操作就可以链接起来,形成一个流水线。


内部迭代:与使用迭代器显示迭代的集合不同,流的迭代操作是在背后进行的。



java8 Stream(流)常见的操作主要有以下几个方面

1)过滤筛选:filter

stream 接口支持filter方法,该操作接收一个谓词Predicate(一个返回bollean的函数)作为参数,并返回一个所有符合谓词元素的流。

2)排序:sort

3)去重:distinct

4)映射:map

map方法,它会接收一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素。

5)查找匹配:anyMatch、allMatch、noneMatch、findFirst、findAny

anyMatch:流中是否有一个元素能匹配给定的谓词。

allMath:流中所有元素是否能匹配给定的谓词。

noneMath:可以确保流中没有任何元素与给定的谓词匹配。

findAny:返回当前流中的任意元素。

findFirst:返回流中的第一个元素。


findAny 和 findFirst 有什么区别?

答案是并行,找到一个元素在并行上限制有很多,如果不关心返回的那个元素,请使用findAny,因为它在使用并行流时限制很少。

6)归约和汇总:reduce、groupingBy

reduce:接收两个参数,归约函数

1)一个初始值,

2)一个 BinaryOperator<T> 来将两个元素结合起来产生一个新值,

求和用lambda    (a,b) ->a+b

求积用lambda    (a,b) ->a*b

groupingBy:对流按照元素进行分组

Map<Currency,List<Transaction>>  transactionByCurrencies =

transactions.stream().collect(

groupingBy

(Transaction::getCurrency));

7)截短流

流支持limit(n),该方法返回一个不超过给定长度的流,所需长度作为常数传递给limit。如果流是有序的,则最多返回前n个元素。请注意,limit也可以用在无序流上,比如源是一个set,这种情况,limit的结果不会以任何顺序排列。

8)跳过元素

流支持ship(n)方法,返回一个扔掉前n个元素的流,如果流中元素不足n个,怎返回一个空流,注意 limit 和 ship 是互补的。

9)流的扁平化(稍后会有专门的一篇文章来讲解流的扁平化)

flatMap方法,可以将生成的单个流合并起来,即扁平化一个流。

几种类型的实际应用案例(以下几个案例是比较常见的stream操作,认真琢磨思考)

案例:



执行交易的交易员。你的经理让你为八个查询找到答案


1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
2)交易员都在哪些不同城市工作过
3)查找所有来自于剑桥的交易员,并且按照姓名排序
4)返回所有交易员的姓名字符串,按字母排序
5)有没有交易员是在米兰工作过?
6)打印生活在剑桥的交易员所有交易额。
7)所有交易中,最高的交易额是多少?
8)找到交易额的最小的交易。


代码实现

实体类创建:

//交易员

public class Trader {
    private final  String name;
    private final  String city;

    public Trader(String n, String c) {
        this.name = n;
        this.city = c;
    }

    public String getCity() {
        return city;
    }

    public String getName() {
        return name;
    }

    public String toString(){
        return "{"+"Trader:"+this.name+"in " + this.city;
    }
}

实体类创建:

//交易信息类

public class Transaction {
    private final Trader trader;
    private final int year;
    private final int value;

    public Transaction(Trader trader, int year, int value){
        this.value = value;
        this.year = year;
        this.trader = trader;
    }

    public Trader getTrader(){
        return  this.trader;
    }
    public int getValue() {
        return value;
    }

    public int getYear() {
        return year;
    }

    public String toString(){
        return "{"+this.trader+","+"year:"+this.year+","+"value:"+this.value+"}";
    }
}

八种查询实现

/*测试用例:执行交易的交易员。你的经理让你为八个查询找到答案
1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
2)交易员都在哪些不同城市工作过
3)查找所有来自于剑桥的交易员,并且按照姓名排序
4)返回所有交易员的姓名字符串,按字母排序
5)有没有交易员是在米兰工作过?
6)打印生活在剑桥的交易员所有交易额。
7)所有交易中,最高的交易额是多少?
8)找到交易额的最小的交易。
* */
public class learnStream {
    public static  void main(String arg[]){
        Trader raoul = new Trader("Raoul","Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brian = new Trader("Brian","Cambridge");

        List<Transaction> transactions = Arrays.asList(
                new Transaction(brian,2011,300),
                new Transaction(raoul,2012,1000),
                new Transaction(raoul,2011,400),
                new Transaction(mario,2012,710),
                new Transaction(mario,2012,700),
                new Transaction(alan,2012,950)
        );

        //1)找出2011年发生的所有交易,并且按照交易额排序(从低到高)
        List<Transaction> tr2011 = transactions.stream()
                .filter(transaction ->transaction.getYear() == 2011)
                .sorted(Comparator.comparing(Transaction::getValue))
                .collect(toList());

        //2)交易员都在哪些不同城市工作过
        List<String> cities = transactions.stream()
                .map(transaction -> transaction.getTrader().getCity())
                .distinct()
                .collect(toList());

        //3)查找所有来自于剑桥的交易员,并且按照姓名排序
        List<Trader> name = transactions.stream()
               .map(transaction -> transaction.getTrader())
                .filter(trader -> trader.getCity().equals("Cambridge"))
                .distinct()
                .sorted(Comparator.comparing(Trader::getName))
                .collect(toList());

        //4)返回所有交易员的姓名字符串,按字母排序
        String traderStr = transactions.stream()
                .map(transaction -> transaction.getTrader().getName())
                .distinct()
                .sorted()
                .reduce("",(n1,n2) -> n1+n2);
        String traderStr2 = transactions.stream()
                .map(transaction -> transaction.getTrader().getName())
                .distinct()
                .sorted()
                .collect(joining());

        //5)有没有交易员是在米兰工作过?
        boolean mailanBased = transactions.stream()
                .anyMatch(transaction -> transaction.getTrader().getCity().equals("Milan"));

        //6)打印生活在剑桥的交易员所有交易额。
        transactions.stream()
                .filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
                .map(Transaction::getValue)
                .forEach(System.out::println);

        //7)所有交易中,最高的交易额是多少?
        Optional<Integer> highestValue = transactions.stream()
                .map(transaction -> transaction.getValue())
                .reduce(Integer::max);

        //8)找到交易额的最小的交易。
        Optional<Transaction> smallestTransaction = transactions.stream()
                .min(Comparator.comparing(Transaction::getValue));

    }

}