Java8新特性-实用版

JAVA8 新特性

1.方法引用&默认方法

1.方法引用
    方法引用通过方法的名字来指向一个方法。
	方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
	//方法引用使用一对冒号 ::
    /*例如*/
    cars.forEach( System.out::println);//循环打印car的内容
2.默认方法(好处:可以不重写一些用不着的方法;同时比抽象类好在可以多继承)
    默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
	//我们只需在方法名前面加个 default 关键字即可实现默认方法
    public interface Vehicle {
       default void print(){
          System.out.println("我是一辆车!");
       }
    }
	//另一个特性是接口可以声明(并且可以提供实现)静态方法
    public interface Vehicle {
       default void print(){
          System.out.println("我是一辆车!");
       }
        // 静态方法
       static void blowHorn(){
          System.out.println("按喇叭!!!");
       }
    }

2.Lambda 表达式

1.语法格式
    (parameters) -> expression 或 (parameters) ->{ statements; }
2.特点
    可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
    可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
    可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
    可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值

3.Stream API

中间操作(返回一个新的流)
方法说明
sequential返回一个相等的串行的Stream对象,如果原Stream对象已经是串行
就可能会返回原对象
parallel返回一个相等的并行的Stream对象,如果原Stream对象已经是并行
的就会返回原对象
unordered返回一个不关心顺序的Stream对象,如果原对象已经是这类型的
对象就会返回原对象
onClose返回一个相等的Steam对象,同时新的Stream对象在执行Close方法
时会调用传入的Runnable对象
close关闭Stream对象
filter元素过滤:对Stream对象按指定的Predicate进行过滤,返回的Stream
对象中仅包含未被过滤的元素
map元素一对一转换:使用传入的Function对象对Stream中的所有元素进行处理,
返回的Stream对象中的元素为原元素处理后的结果
mapToInt元素一对一转换:将原Stream中的使用传入的IntFunction加工后返回
一个IntStream对象
flatMap元素一对多转换:对原Stream中的所有元素进行操作,每个元素会有
一个或者多个结果,然后将返回的所有元素组合成一个统一的Stream并返回;
distinct去重:返回一个去重后的Stream对象
sorted排序:返回排序后的Stream对象
peek使用传入的Consumer对象对所有元素进行消费后,返回一个新的包含
所有原来元素的Stream对象
limit获取有限个元素组成新的Stream对象返回
skip抛弃前指定个元素后使用剩下的元素组成新的Stream返回
takeWhile如果Stream是有序的(Ordered),那么返回最长命中序列
(符合传入的Predicate的最长命中序列)组成的Stream;如果是无序的,
那么返回的是所有符合传入的Predicate的元素序列组成的Stream。
dropWhile与takeWhile相反,如果是有序的,返回除最长命中序列外的所有
元素组成的Stream;如果是无序的,返回所有未命中的元素组成的Stream。
终端操作(返回最终的结果)
方法说明
iterator返回Stream中所有对象的迭代器;
spliterator返回对所有对象进行的spliterator对象
forEach对所有元素进行迭代处理,无返回值
forEachOrdered按Stream的Encounter所决定的序列进行迭代处理,无返回值
toArray返回所有元素的数组
reduce使用一个初始化的值,与Stream中的元素一一做传入的二合运算后返回最终的值。
每与一个元素做运算后的结果,再与下一个元素做运算。它不保证会按序列执行整个过程。
collect根据传入参数做相关汇聚计算
min返回所有元素中最小值的Optional对象;如果Stream中无任何元素,那么返回的
Optional对象为Empty
max与Min相反
count所有元素个数
anyMatch只要其中有一个元素满足传入的Predicate时返回True,否则返回 False
allMatch所有元素均满足传入的Predicate时返回True,否则False
noneMatch所有元素均不满足传入的Predicate时返回True,否则False
findFirst返回第一个元素的Optioanl对象;如果无元素返回的是空的Optional;
如果Stream是无序的,那么任何元素都可能被返回。
findAny返回任意一个元素的Optional对象,如果无元素返回的是空的Optioanl。
isParallel判断是否当前Stream对象是并行的
常见应用
1.map和peek的区别 //(peek可以改变原对象的值,而map主要将原对象的值进行映射重新生成新的集合)
//使用peek修改List集合中user的年龄
ArrayList<UserEntity> arrs = (ArrayList<UserEntity>) userEntities.stream()
                .peek(user -> user.setAge(user.getAge() + 5)).collect(Collectors.toList());
//map应用:将userEntities集合中的年龄收集起来重新放入一个集合中
        ArrayList<Integer> arrayList =  (ArrayList<Integer>)userEntities.stream().map(user -> user.getAge()).collect(Collectors.toList());


2. filter 通过设置的条件过滤出元素
 long count = strings.stream().filter(string -> string.isEmpty()).count();


3.sorted 方法用于对流进行排序
random.ints().limit(10).sorted().forEach(System.out::println);


4. Collectors 实现了很多归约操作//即中间操作后转换为某种结果
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());


5.summaryStatistics //主要用于int、double、long等基本类型上,可以获取一些统计结果
int1List.stream().mapToInt(x->x).summaryStatistics();


6.stream 合并两个list去重
    List<String> collect = Stream.of(listA, listB)
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());


7.去除listA中包含listB的元素
    listA.removeIf(a->listB.stream().anyMatch(b->b.getName().equals(a.getName())));

8.reduce使用
   	1. reduce(BinaryOperator<T> accumulator);
    2. reduce(T identity, BinaryOperator<T> accumulator);
	3. <U> U reduce(U identity,
                 BiFunction<U, ? super T, U> accumulator,
                 BinaryOperator<U> combiner);
  //对int1List元素进行求和,1表示初始值
  int1List.stream().mapToInt(x -> x).reduce(1, Integer::sum);

9.对list中元素按照某个属性去重并求和另一个属性
 List<Entity> result = list.stream()
        // 表示name为key,接着如果有重复的,那么从Pool对象o1与o2中筛选出一个,这里选择o1,
        // 并把name重复,需要将value与o1进行合并的o2, 赋值给o1,最后返回o1
        .collect(Collectors.toMap(Entity::getName, a -> a, (o1,o2)-> {
          o1.setValue(o1.getValue() + o2.getValue());
          return o1;
        })).values().stream().collect(Collectors.toList());
    return result;
  }

4.Date Time API

1.时间处理类(具体的方法很简单:看名称即可看出方法作用)
    java.time.LocalDateTimejava.time.LocalDatejava.time.LocalTime
    //获取当前时间、当前月份、当前月份减一、日期比较、日期格式化、计算时间差 等等使用链式编程就可以获取
2.JSON序列化与反序列化接收前台参数问题
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

5.Optional 类API

1.说明 java.util.Optional
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存nullOptional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
2.使用 
   1.构建Optional:empty()of(T value)ofNullable(T value)
   //of参数不可为null,isPresent()为true;empty().isPresent()为false;ofNullable(null).isPresent()为false
   
   2.orElse(T value) orElseGet(Supplier o) orElseThrow(Supplier o)
   //如果Optional为空则返回ofElse的参数值
    
   3.map:为空返回 Optional.empty;否则返回一个新的 Optional:函数 mapper 在以 value 作为输入时的输出值;可以多次使用map操作
     Optional<String> username = Optional.ofNullable(getUserById(id))
		.map(user -> user.getUsername())
		.map(name -> name.replace('_', ' '));
   4. flatMap: map 方法参数中的函数 mapper 输出的是值,然后 map 方法会使用 Optional.ofNullable 将其包装为 Optional;而 flatMap 要求参数中的函数 mapper 输出的就是 Optional
     Optional<String> username = Optional.ofNullable(getUserById(id))
		.flatMap(user -> Optional.of(user.getUsername()))
		.flatMap(name -> Optional.of(name.toLowerCase()));
   5. filter: 接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty
3.业务使用:
    //如果库里不存在则new一个新的返回
    Optional.of(getAnimalById).orElse(new Animal("猫科动物1","哆啦A梦",15));

6.CompletableFuture 异步多线程执行(参考文档https://mp.weixin.qq.com/s/f8Bh–WhwMw0y8txmmNb-A)

JDK5新增了Future接口,用于描述一个异步计算的结果。
虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,我们必须使用Future.get()的方式阻塞调用线程。

//CompletableFuture源码中有四个静态方法用来执行异步任务:
「supplyAsync」执行任务,支持返回值。
「runAsync」执行任务,没有返回值。
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}  
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}  
public static CompletableFuture<Void> runAsync(Runnable runnable){..}  
public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}  

//获取结果的方式
//方式一  
public T get()  
//方式二  
public T get(long timeout, TimeUnit unit)  
//方式三  
public T getNow(T valueIfAbsent)  
//方式四  
public T join()  
join方法获取结果方法里不会抛异常,但是执行结果会抛异常,抛出的异常为CompletionException
get方法获取结果方法里将抛出异常,执行结果抛出的异常为ExecutionException

//异步回调方法
1、thenRun/thenRunAsync
通俗点讲就是,「做完第一个任务后,再做第二个任务,第二个任务也没有返回值」
2、thenAccept/thenAcceptAsync
第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。
3、 thenApply/thenApplyAsync
表示第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,并且回调方法是有返回值的。

//异常回调CompletableFuture的任务不论是正常完成还是出现异常它都会调用 「whenComplete」这回调函数。
「正常完成」:whenComplete返回结果和上级任务一致,异常为null;
「出现异常」:whenComplete返回结果为null,异常为上级任务的异常;
即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。

//多任务组合问题
1AND组合关系
thenCombine / thenAcceptBoth / runAfterBoth都表示:「当任务一和任务二都完成再执行任务三」。
区别在于:
「runAfterBoth」 不会把执行结果当做方法入参,且没有返回值
「thenAcceptBoth」: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值
「thenCombine」:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值
2OR组合关系
applyToEither / acceptEither / runAfterEither 都表示:「两个任务,只要有一个任务完成,就执行任务三」。
区别在于:
「runAfterEither」:不会把执行结果当做方法入参,且没有返回值
「acceptEither」: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值
「applyToEither」:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值

3、多任务组合
「allOf」:等待所有任务完成
「anyOf」:只要有一个任务完成

//CompletableFuture使用有哪些注意点
1Future需要获取返回值,才能获取异常信息
2CompletableFutureget()方法是阻塞的
CompletableFutureget()方法是阻塞的,如果使用它来获取异步调用的返回值,需要添加超时时间。
3、不建议使用默认线程池
CompletableFuture代码中又使用了默认的 「ForkJoin线程池」,处理的线程个数是电脑 「CPU核数-1」。在大量请求过来的时候,处理逻辑复杂的话,响应会很慢。一般建议使用自定义线程池,优化线程池配置参数。
4、自定义线程池时,注意饱和策略
CompletableFutureget()方法是阻塞的,我们一般建议使用future.get(5, TimeUnit.SECONDS)。并且一般建议使用自定义线程池。
但是如果线程池拒绝策略是DiscardPolicy或者DiscardOldestPolicy,当线程池饱和时,会直接丢弃任务,不会抛弃异常。因此建议,CompletableFuture线程池策略最好使用AbortPolicy,然后耗时的异步线程,做好线程池隔离
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有什么是应该

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值