A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

流的简介

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

剖析这个定义

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

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

       数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如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));    }

2 个回复

倒序浏览
回复 使用道具 举报
~(。≧3≦)ノ⌒☆
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马