Java 实战 1
线程池
SpringBoot + 线程池 使用
○ 自定义线程池
■ 定义一个线程池配置类
●
■ 定义一个专门执行异步操作的线程服务类,用来调用线程池执行异步任务
●
■ 调用线程服务类执行任务
● threadService.updateXXX(lotteryCalculatePerMapper,id)
○ 使用 SpringBoot 自带的线程池
■ 通过上线文查看 SpringBoot 默认注册的线程池
●
■ 在需要的 Service 中使用
● 注入线程池
○ @Autowired private ThreadPoolTaskExecutor threadPoolTaskExecutor;
● 在主线程中使用异步线程池执行多个任务
○
■ 针对 Web 场景进行异步操作
● 无返回值
○ @Async("taskExecutor") @SneakyThrows public void testVoid(){ Thread.sleep(1000); log.info("testVoid。。。"); }
● 有返回值
○
函数式编程(Lambda)
概述
○ 主要作用
■ 处理大数据量集合效率更高
■ 处理大数据量集合效率更高
■ 简化代码
○ 编程思想
■ 函数式编程思想
■ 匿名内部类
Lambda 表达式
○ 语法糖、可推导可省略
○ 基本格式:(参数列表)->{代码}
○ 省略规则
■ 参数类型可以省略
■ 方法体只有一句代码时大括号 return 和唯一一句代码的分号可以省略
■ 方法只有一个参数时小括号可以省略
Stream 流
○ Idea 工具可支持 Stream 流调试
■ Trace Current Stream Chain
○ 常用操作
■ 创建流
● 集合对象.stream().
● Arrays.stream(数组). ... 或者使用 Stream.of(数组)........
● 集合对象.stream().
● Arrays.stream(数组). ... 或者使用 Stream.of(数组)........
● map.entrySet().stream()......
■ 中间操作
● filter
○ 对流中元素进行过滤,符合条件的才会留存下来
○ list/arrays/map.stream.filter(xx-> boolean )....
● map
○ 对流中元素进行计算或者转换
○ list/arrays/map.stream.map(xx-> {转换逻辑 return y } )....
● distinct
○ 可以去除流中的重复元素
○ 底层依赖 object 的 equals 方法,判断对象是否重复,可进行重写 equals 方法
○ list/arrays/map.stream.distinct()....
● sorted
○ 可以对流中元素进行排序
○ 针对对象的排序,可以实现 Comparable<xxx> 接口的 compareTo 方法
○ list/arrays/map.stream.sorted().... 或者 list/arrays/map.stream.sorted((o1,o2)-> o1.xxx > o2.xxx)....
● limit
○ 可以限制流的元素的最大长度
○ list/arrays/map.stream.limit(n)....
● filter
○ 对流中元素进行过滤,符合条件的才会留存下来
○ list/arrays/map.stream.filter(xx-> boolean )....
● map
○ 对流中元素进行计算或者转换
○ list/arrays/map.stream.map(xx-> {转换逻辑 return y } )....
● distinct
○ 可以去除流中的重复元素
○ 底层依赖 object 的 equals 方法,判断对象是否重复,可进行重写 equals 方法
○ list/arrays/map.stream.distinct()....
● sorted
○ 可以对流中元素进行排序
○ 针对对象的排序,可以实现 Comparable<xxx> 接口的 compareTo 方法
○ list/arrays/map.stream.sorted().... 或者 list/arrays/map.stream.sorted((o1,o2)-> o1.xxx > o2.xxx)....
● limit
○ 可以限制流的元素的最大长度
○ list/arrays/map.stream.limit(n)....
● skip
○ 跳过流中元素的前 n 个元素,返回剩下元素
○ list/arrays/map.stream.skip(n)....
● flatmap
○ map 只能把一个对象转换成另一个对象;而 flatMap 可以把一个对象转换成多个对象作为流中元素,同时也可以将多个对象转换为一个对象
○ list/arrays/map.stream.flatmap(xxx-> {... return yyy})....
■ 终结操作
● foreach
○ 循环遍历
○ list/arrays/map.stream.foreach(xx-> {......})
● count
○ 获取流中元素个数
○ list/arrays/map.stream.count()
● min&max
○ 获取流中元素最小值/最大值
○ list/arrays/map.stream.min((s1,s2)-> s1 - s2).get()/max((s1,s2)-> s1 - s2).get())
● collect
○ 把当前流中元素转换为一个集合
○ list/arrays/map.stream.collect(Collectors.toList()) 或 list/arrays/map.stream.collect(Collectors.toSet()) 或 list/arrays/map.stream.collect(Collectors.toMap(xxx-> xxx.getAAA(),xxx.getBBB()))
● anyMatch
○ 用来判断是否有任意符合匹配条件的元素,结果为 boolean 类型
○ list/arrays/map.stream.anyMatch(xx-> boolean)
● allMatch
○ 用来判断是否所有符合匹配条件的元素,结果为 boolean 类型,只有所有都满足才返回 true,否则返回 false
○ list/arrays/map.stream.allMatch(xx-> boolean)
● noneMatch
○ 用来判断流中都不符合条件的元素,结果为 boolean 类型,只有所有都满足才返回 true,否则返回 false
○ list/arrays/map.stream.noneMatch(xx-> boolean)
● findAny
○ 获取流中任意一个元素,不能保证一定获取第一个元素,结果有随机性
○ list/arrays/map.stream.findAny().ifPresent(xxx-> {.....})
● findFirst
○ 获取流中第一个元素
○ list/arrays/map.stream.findFirst().ifPresent(xxx-> {.....})
● reduce
○ 对流中的数据按照你制定的计算方式计算出一个结果
○ 将 stream 流中的元素组合起来,可以传入一个初始值,它会按照我们计算方式依次拿流中元素和初始值的基础上进行计算,计算结果再和后面的元素计算返回
○ 求和:list/arrays/map.stream.map(xxx-> yyy).reduce(0,(a,b)-> a+b) 最大值:list/arrays/map.stream.map(xxx-> yyy).reduce(INTEGER.MAX_VALUE,(a,b)-> a>b ? a : b) 最小值:list/arrays/map.stream.map(xxx-> yyy).reduce(INTEGER.MIN_VALUE,(a,b)-> a<b ? a : b)
Optional
○ 可以用来避免对象获取属性时空指针异常问题
○ Optional.ofNullable(xxx).ifPresent(a-> {..........})
○ 获取安全值,如果我们期望想要获取非空值但又不想判空,不推荐直接使用 get()方法
■ orElseGet
● Optional.ofNullable(xxx).orElseGet(()-> new xxx());
■ orElseThrow
● Optional.ofNullable(xxx).orElseThrow((Supplier<Throwable>)()-> new RuntimeException("xxx 为空"));
○ 过滤用法:filter
■ Optional.ofNullable(xxx).filter(xxx-> boolean).ifPresent(a-> {..........})
○ map
■ Optional.ofNullable(xxx).map(xxx-> {... return aaa}).ifPresent(a-> {..........})
函数式接口
○ 只有一个抽象方法的接口我们称之为函数接口,JDK 的函数式接口都加上了 @FunctionalInterface 注解进行标识,实战中可自定义函数式接口并加上 @FunctionalInterface 注解
方法引用
○ 在使用 lambda 时,如果方法体中只有一个方法的调用的话(包括构造方法),我们可以用方法引用进一步简化代码
○ 类名::方法名
○ 如果是静态方法,可以使用类名::方法名
○ 如果我们在重写某个类的方法时,方法体只有一行代码,这行代码调用了某个对象的成员方法且该成员方法的所有参数按照顺序传入了这个成员方法中,此时 可以简写 实例名::方法名
○ 构造器引用: 类名::new
■ 如果我们在重写方法时,方法体只有一行代码,并且这行代码是调用了某个类的构造方法,我们把重写的抽象方法中所有参数按照顺序传入了这个构造方法中,这个时候可以使用引用构造器简写
高级用法
○ 主要是在大数据量情况下,如果有比较、运算等场景,为避免频繁拆装箱导致耗时问题,可使用 mapToInt、MapToLong 等替代 map 方法
■ mapToInt
■ mapToLong
■ mapToDouble
○ 并行流:parallel
■ Stream.of(xxx).parallel().filter(x-> ....).map(x-> ....).reduce(x-> ...)... 或者 使用 xxxx.parallelStream().....
■ 当集合遍历有多个操作时并且数据量较大时可以考虑采用并行流
版权声明: 本文为 InfoQ 作者【thinkers】的原创文章。
原文链接:【http://xie.infoq.cn/article/743080d195c861c177145221d】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论