前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4.2.Java8 Stream简单的应用

4.2.Java8 Stream简单的应用

原创
作者头像
itjim
修改2019-11-25 14:20:46
6890
修改2019-11-25 14:20:46
举报
文章被收录于专栏:springboot解析springboot解析

流的简介

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

剖析这个定义

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

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

       数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如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方法,可以将生成的单个流合并起来,即扁平化一个流。

2.Java8 Stream经典示例

示例一:现在有一个List<User> 的集合,如何把这个list转换成Map<Integer, User> 其中,key是user id,value是User对象

class User {

private int id;

private String name;

public User(int id, String name) {

this.id = id;

this.name = name;

}

public int getId() {

return id;

}

public String toString() {

return "User [id=" + id + ", name=" + name + "]";

}

}

代码如下:

List<User> users = Arrays.asList(new User(1, "Tomcat"), new User(2, "Apache"), new User(3, "Nginx"));

Map<Integer, User> map = users.stream().collect(Collectors.toMap(obj -> obj.getId() , obj -> obj));

System.out.println(map);

或者使用方法的引用

Map<Integer, User> map = users.stream().collect(Collectors.toMap(User::getId , obj -> obj));

最后,输出结果

{1=User [id=1, name=Tomcat], 2=User [id=2, name=Apache], 3=User [id=3, name=Nginx]}

示例二:如何把list中的每个map中的id取出来,转换成list<String>

有如下List<Map<String, String>>

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

Map<String, String> map1 = new HashMap<>();

map1.put("id", "101");

map1.put("name", "Tomcat");

Map<String, String> map2 = new HashMap<>();

map2.put("id", "102");

map2.put("name", "Apache");

Map<String, String> map3 = new HashMap<>();

map3.put("id", "103");

map3.put("name", "Nginx");

list.add(map1);

list.add(map2);

list.add(map3);

参考代码如下:

List<String> ids = list.stream().map(entity -> entity.get("id")).collect(Collectors.toList());

System.out.println(ids);

或者

List<Object> ids = Arrays.asList(list.stream().map(entity -> entity.get("id")).toArray());

输出结果:

[101, 102, 103]

示例三:如何把url的请求参数(如:type=1&from=APP&source=homePage)转换成Map<String, String>

参考代码:

String queryString = "type=1&from=APP&source=homePage";

Map<String, String> map = Stream.of(queryString.split("&")).map(obj -> obj.split("=")).collect(Collectors.toMap(entry -> entry[0], entry -> entry[1]));

System.out.println(map);

输出结果:

{from=APP, source=homePage, type=1}

示例四:把List<String>转换成List<Integer>

List<String> strs = Arrays.asList("1","2","3");

List<Integer> ints = strs.stream().map(obj -> Integer.valueOf(obj)).collect(Collectors.toList());

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

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

实体类创建:

//交易员

代码语言:javascript
复制
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;
    }
}

实体类创建:

//交易信息类

代码语言:javascript
复制
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+"}";
    }
}

八种查询实现

代码语言:javascript
复制
/*测试用例:执行交易的交易员。你的经理让你为八个查询找到答案
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));

    }

}

示例六:将流中的数据转成集合类型

一、将数据收集进一个列表(Stream 转换为 List,允许重复值,有顺序)

//1.将数据收集进一个列表(Stream 转换为 List,允许重复值,有顺序)

//创建流

Stream<String> language = Stream.of("java", "python", "C++","php","java");

List<String> listResult = language.collect(Collectors.toList());

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

//2.stream()代替流

List<String> list = Arrays.asList("java", "python", "C++","php","java");

List<String> listResult = list.stream().collect(Collectors.toList());

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

输出结果为:

二、将数据收集进一个集合(Stream 转换为 Set,不允许重复值,没有顺序)

//1.将数据收集进一个集合(Stream 转换为 Set,不允许重复值,没有顺序)

Stream<String> language = Stream.of("java", "python", "C++","php","java");

Set<String> setResult = language.collect(Collectors.toSet());

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

输出结果为:

三、用自定义的实现Collection的数据结构收集

List<String> list = Arrays.asList("java", "python", "C++","php","java");

//用LinkedList收集

List<String> linkedListResult = list.stream().collect(Collectors.toCollection(LinkedList::new));

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

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

//用CopyOnWriteArrayList收集

List<String> copyOnWriteArrayListResult = list.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));

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

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

//用TreeSet收集

TreeSet<String> treeSetResult = list.stream().collect(Collectors.toCollection(TreeSet::new));

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

输出结果为:

四、对Stream的字符串拼接

List<String> list = Arrays.asList("java", "python", "C++","php","java");

//直接将输出结果拼接

System.out.println(list.stream().collect(Collectors.joining()));

//每个输出结果之间加拼接符号“|”

System.out.println(list.stream().collect(Collectors.joining(" | ")));

//输出结果开始头为Start--,结尾为--End,中间用拼接符号“||”

System.out.println(list.stream().collect(Collectors.joining(" || ", "Start--", "--End")));

输出结果为:

五、其他还有partitioningBy(),分类成一个key为True和Flase的Map。

例如

List<String> list = Arrays.asList("java", "python", "C++","php","java");

Map<Boolean, List<String>> result = list.stream().collect(partitioningBy(s -> s.length() > 2));

六、collectingAndThen(),收集之后继续做一些处理。

例如

List<String> list = Arrays.asList("java", "python", "C++","php","java");

//收集后转换为不可变List

ImmutableList<String> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), ImmutableList::copyOf));

总结:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 流的简介
  • java8 Stream(流)常见的操作主要有以下几个方面
  • 2.Java8 Stream经典示例
    • 示例一:现在有一个List<User> 的集合,如何把这个list转换成Map<Integer, User> 其中,key是user id,value是User对象
      • 示例二:如何把list中的每个map中的id取出来,转换成list<String>
        • 示例三:如何把url的请求参数(如:type=1&from=APP&source=homePage)转换成Map<String, String>
          • 示例四:把List<String>转换成List<Integer>
            • 示例五:执行交易的交易员。你的经理让你为八个查询找到答案
              • 代码实现
            • 示例六:将流中的数据转成集合类型
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档