Java8实战,

 summary

4,lamda表达式相当于匿名函数的简单写法,通常用在比较器,gui的注册事件,线程注册

  

7,怎么写好lambda,注意:(行为参数化)要提前准备好对象(资源)通过形参传个lambda

  • 将一个行为抽象多出来多态,这个是我们经常做的,也就是有@FunctionalInterface的接口,java8帮我写了很多
  • Java8帮我们写了很多如何使用他的方法如Lists.tranform, 和 comparator.camparing,和流,只要我们补上(lamda), 甚至可以用方法引用(如果有的话)
  • 写lambda注意parameter 和 return type

UnaryOperator

 

 

Supplier

1,

@FunctionalInterface
public interface Supplier<T> {

2,    T get();

3,

Supplier<Apple> c1 = Apple::new
Apple a1 = c1.get();

 consumer接口

1,

@FunctionalInterface
public interface Consumer<T> {

2,void accept(T t);

3,主要用来消费的

 

function 接口

1,public interface Function<T, R> {

2,T apply(F input);

3,主要是用来转换东西的

4,函数复合,

  • andThen    f.andThen(g)    数学上会写作g(f(x))
  • compose   f.compose(g);   数学上会写作f(g(x))

Predicate接口

1,充当一个参数化的返回Boolean比较方法

2,public interface Predicate<T> {

3,boolean test(T t);

4,能动态替换返回boolean的函数

4.5, a.or(b).and(c) = (a || b) && c ,而且只能是同个参数类型

5,基本类型装箱问题,

DoublePredicate
boolean test(double value);//有对应的原始类型特化接口

 

 

lambda用法

1,

2,这里注意一下list是实例

 

 

list.sort的parameter要的是一个comparator,我们通过comparator.comparing返回一个给他,里面少了 apply方法实现,我们补充上就可以,compareto是object方法,已经由转成int的重写了,自己不用重写

 

 

 

 

3,

4,基本lambda语法

 

5,基本用法

6,在面向资源编程的lambda,不需要重复打开资源和关闭资源

7,lambda也有匿名函数的问题

8,方法引用

  • 静态方法引用,(例如Integer的parseInt方法,写作Integer::parseInt)。
  • 实例方法引用,(例如String的length,String::length
  • 方法体里面的方法引用,进一步的方法引用
  • 方法里面有沒有实现的方法引用,记得要补上

 

 

     

 

 

 9,比较器复合

  • comparetor的comparing方法相当于帮我实现了compare方法,只需要我们传递lambda或者方法引用进去
  • 翻转:list.sort(comparing(Object::getXXX).reveserd());
  • 同样的时候添加第二个比较器,第二个是comparator类型, list.sort(Comparator.comparing(Integer::intValue).reversed().thenComparing(Integer::compareTo));
  • 这些操作在上一条的基础上改

 

 comparator是一个@function Interface类,compare是他的接口,comparing是他的Java8静态方法,通常 comparator.comparing这样出现,实现了 a.compare(b),方式给一个apply接口,开放出要比较的数

对象之间比较通常用来自comparable的compareTO方法,需要自己实现,但实际比较时候通常只用int或者string这些,这些已经默认实现了compareto

 

 

 

 stream

 流依赖lambda,要关注parameter和return type,list<string> = stream<String>,流相当做了下面内容,里面的数据轮流调用 lambda的内容,帮我们放在那里,filter用了predicate.test,map用了function.apply,foreach用了consumer.accept,(还有个个supplier.get)没有用上

 

 

 

 

1,更加简单的利用多cpu

 

 

2,基本概念

 流是“从支持数据处理操作的源生成的一系列元素”。
 流利用内部迭代:迭代通过filter、map、sorted等操作被抽象掉了。
 流操作有两类:中间操作和终端操作。
 filter和map等中间操作会返回一个流,并可以链接在一起。可以用它们来设置一条流 水线,但并不会生成任何结果。
 forEach和count等终端操作会返回一个非流的值,并处理流水线以返回结果。  流中的元素是按需计算的。
3,filter,筛选和切片
4,limit,skip
5,map,映射

 

 

  • stream的意思就是拆开每个item,list<String>  =  Stream<string>
  •  

     

  • 第二个apply从本来的T,转成一个R流,返回代码是,创建一个流,然后map就行
  • flatmap是两层循环时候,里面的循环能和外面的循环交流,然后拿出来作为流返回,传统循环没有这个
  • 如果是两层循环,不想在里面交流时候,可以用foreach
  •  

  •  

     

6,查找和匹配

  • anyMatch方法返回一个boolean,因此是一个终端操作。 
    if(menu.stream().anyMatch(Dish::isVegetarian)){
    System.out.println("The menu is (somewhat) vegetarian friendly!!"); }  

  • allMatch方法的工作原理和anyMatch类似,但它会看看流中的元素是否都能匹配给定的谓
  boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000); 
  • 和allMatch相对的是noneMatch。
  boolean isHealthy = menu.stream()

  .noneMatch(d -> d.getCalories() >= 1000);  

  • findFirst和findAny

7,归约

  • reduce , 
    累加:int sum = numbers.stream().reduce(0, Integer::sum);

   最大最小值:Optional min = numbers.stream().reduce(Integer::min);  

8,并发的有状态和无状态(状态是比如排序的时候有内部状态,有界无界是看返回的是稳定还是不稳定

9,优化自动装箱,

  • int calories = menu.stream()  .mapToInt(Dish::getCalories)  .sum();  //IntStream才有sum方法
  • 自动装箱

    IntStream intStream = menu.stream().mapToInt(Dish::getCalories)
    Stream<Integer> stream = intStream.boxed();

  • Stream<int[]> instStream  = IntStream.rangeClosed(1, 3).boxed().map(a->new int[]{a});装箱和不装箱map返回是不一样的

 

 

 10,小结

11,collect = 有状态的操作(计算平均数,总数这些,涉及到前面的)

collect方法会接受一个collector 作为 parameter,由a as accumulator作为中间收集器,T作为操作类型,R作为返回类型,也就是说R由collector决定

 

三个重载的collers.reducing方法,第一个是流里面比较,第二个是运行有初始值(但是是返回类型),返回流的类型,第三个是有初始值,还能转换比较对象

 

 comparator.groupingby是一个接受apply函数,根据return值作为key,放进一个map

 

 两个groupingby, 第一次的apply后的值作为key值,后面加个返回d,类型的collector, 也就是说后面那次(已经被groupingby分流的数据)不一定是groupingby,也可以是上面的reducing

 

 

 

 

 

 分区,和根据true,和false的Boolean分两个

 

 

 

 

 流的并行,将原来单个线程的东西放在多个线程,但也有线程共享变量的危险,

使用的标准的测试,数据小还不如不用多线程

 

 

 

 

Java8重构小实例

1,策略模式,类似predicate替换策略

2,模板方法,

3,观察者模式,注册的时候写上方法(经典写法了

4,责任链模式,传递下去,在注册的时候像观察者模式差不多

5,传统简单工厂,用map做工厂,和supplier

 

CompletableFuture

future主要思想是非阻塞,可以做其他东西,但是没有异步,completableFuture是帮完成了异步,返回消息然后干嘛

 

 

 

 

 

 

 

类似JavaScript的promise,

 

 

 然而,get还是会阻塞, 实现了Future和CompletionStage接口,保留了Future的优点,并且弥补了其不足。

 

即对结果的异步编程,可以直接通过thenAccept、thenApply、thenCompose等方式将前面异步处理的结果交给另外一个异步事件处理线程来处理。

简单示范也有future.get的功能

 

thenAccept 直接消费

 

 

 

消费了再传给下个一

 

 

thenRun,直接runnable一个线程

 

thenApply 和 thenCompose,thenApply是直接转换,thenCompose是再新开个线程

 

 

 

 

 

 

 

 

 

 异常处理,直接抛出然后用handle

 

 

 

 

 

 这个更像我们的老方法,get可以用try/catch包围

 

 并行的方法,调用其他线程,上面说的是异步,用的是同一个线程

 

 

 time

都是immutable

 

 

 

 

 

 机器使用的

 

duration 比 period精确,用在milliSecond和nanoSecond

 

 

 

 

 

 

 

 

 由于是mutable的, 所以修改方法回产生新例子

 

 TemporalAdjuster

 

 

 

DateTimeFormat

 

 

 

 

 

 

 

 添加时区信息:ZoneId, ZonedDateTime

 

 

 

 

 

 

 

 

 

 格林威治时间,utc/Greenwich ZoneOffset

 

 

 

 

posted on 2019-05-09 04:11  Kooing  阅读(220)  评论(0)    收藏  举报

导航