java8 新特性 实战详解 stream lambda 以及函数

下期写下 effctive java,以及 java puzzlers读后感


基础数据

class PersonSupplier implements Supplier<Person> {
     private int index = 0;
     private Random random = new Random();
     @Override
     public Person get() {
     return new Person(++index, "StormTestUser" + index, random.nextInt(100));
     }
}

代码紧凑些,为了减少行.

class Person {

    private Integer id; 
    private String name;    
    private Integer age;        
    public Person() {
        super();
    }       
    public Person(Integer id, String name, Integer age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }   
    get、set省略
}

语法详解

      Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。
同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程

Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序

点击蓝字快速到节点
1. 流操作
2. 常用流的实战方法
3. list 常用实战方法
4. list按某种条件分组转换成map


流操作

  • Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
  • Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
    在对于一个 Stream 进行多次转换操作 (Intermediate 操作),每次都对 Stream 的每个元素进行转换,而且是执行多次,这样时间复杂度就是 N(转换次数)个 for 循环里把所有操作都做掉的总和吗?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。
  • 还有一种操作被称为 short-circuiting。用以指:
    对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
    对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
Intermediate:
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal:
forEach、 forEachOrdered、 toArray、 reduce、 collect、 minmax、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
Short-circuiting:
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

常用构造流的方法

Stream stream = Stream.of("a", "b", "c");

//构造流并循环
IntStream.of(1, 2, 3).forEach(System.out::println);

IntStream.of(1, 2, 3).forEach(System.out::print);

IntStream.of(1, 2, 3).forEach(a -> System.out.print("\t美问"+a));

list常用实战方法


//自动创建3个 对象
List<Person>  list = Stream.generate(new PersonSupplier()).limit(3).
                    collect(Collectors.toList());

Stream.generate(new PersonSupplier()).limit(3).collect(Collectors.toList()).forEach(p ->System.out.println("\n"+p.getName()+"---"+p.getAge())); 


//输出集合中id,以逗号分割
List<Integer> idList = list.stream().map(Person :: getId).collect(Collectors.toList());

//输出String,集合中id,以逗号分割
String meiwen = list.stream().map(Person::getId).map(String::valueOf).collect(Collectors.joining(","))

//list转map(且对对象的field进行加1操作)
Map<Integer,Person> map = list.stream().peek(p -> p.setId(p.getId()+1)).collect(Collectors.toMap(Person :: getId, p -> p));


//map集合循环

        Stream.generate(new PersonSupplier()).limit(10).peek(p -> p.setId(p.getId()+1))
        .collect(Collectors.toMap(Person :: getId, p -> p)).forEach((k,v) -> System.out.println(k +"--"+v.getName()));;

list按某种条件分组转换成map

前面都各种示例的操作,这个就留给大家自己摸索了
目前1.8版本 stream 没有对map进行改进,坊间看到9 的更新内容没这块的说明


并发操作

        List<String> listString = Stream.generate(UUID.randomUUID() :: toString)
                .limit(10000000).collect(Collectors.toList());
        Long time = System.nanoTime();

        listString.parallelStream().sorted();

        System.out.println(System.nanoTime()-time);

        time = System.currentTimeMillis();
        listString.stream().sorted();
        System.out.println(System.nanoTime()-time);

输出

7397065
111305163406539

函数式编程初探

  1. 代码简洁,开发快速
  2. 接近自然语言,易于理解
  3. 易于并发编程
  4. 不修改变量值
表达式(1 + 2) * 3 - 1

写成函数式语言
subtract(multiply(add(1,2), 3), 1)

更自然的表述  
add(1,2).multiply(3).subtract(4)

干货

## 亲们分享是福,动动小手转下 ##

在这里推荐这篇文章

深入理解java 8 lambda

作者 Apocalypsa 签名:沉思与反省
8年开发经验,发表文章不多。篇篇经典,看的出来是用心在分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值