Java 8让变成变得更容易,代码变得更简洁。有lambda表达式,接口的默认方法,流,新的日期和时间API,Optional还有CompletableFuture。
1 lambda表达式
使用匿名类表示不同的行为并不令人满意,代码啰嗦,它可以让我们很简单的表示一个行为或者代码传递。
例如启动线程读取阻塞队列里面的数据。
private void messageProcess() {
Runnable runnable = () -> {
// ... ...
while (true) {
// ... ...
// 这里是使用drainTo的一个最佳实践,
// - drainTo是非阻塞的
// - take是阻塞的
// 利用take保证有数据才进行后续操作,然后通过drainTo批量读取提高效率
entity = mqttMsgBlockingQueue.take();
if (entity == null) {
continue;
}
size = mqttMsgBlockingQueue.drainTo(entities, 32);
if (size == 512) {
log.warn("entity number is 512, system is busy");
}
entities.add(entity);
// ... ...
}
};
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(runnable); // 这里通过lambda表达式出入Runnable
thread.setName("process-parameter-thread-" + i);
thread.start();
}
}
lambda表达式格式: () -> {}
()中是参数,{}中是lambda的主题。
2 默认方法
Java 8以前,实现接口的类必须为借口中定义的每所有方法提供实现,或者从父类中继承他的实现。如果一个接口增加了新方法了,实现了所有这个接口的类全都需要跟着修改,这是多么让人抓狂的事情。 Java 8的接口中现在支持声明方法的同时提供实现。如果实现接口的类不显示的提供该方法的具体实现,就会继承默认的实现。这种机制不仅可以简化实现类的开发,并不用实现所有的接口;更能保证接口平滑的进行优化和演进。
如采集线程需要实现的接口实现:
public interface DataAcquisitionWorker {
void execute(final ScheduleEvent event);
String genKey(String deviceName);
default int getThreadSize(ScheduleEvent event) {
return 10;
}
default int getQueueSize(ScheduleEvent event) {
return 40;
}
}
通过default定义了默认的采集线程的工作线程数量和队列的长度。这样就可以保证很多实现可以使用默认的数值,不用自己定制。
3 流
流是JavaAPI的新成员,提供声明式处理数据集合的方式,并且可以透明的进行并行处理。
工艺参数返回的时候,需要通过分级的方式返回数据,数据格式如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"设备ID:
{ "工艺参数1":
[
{
"value": "120",
"acquisitionTime": "2019-06-25 16:35:20"
},
{
"value": "121",
"acquisitionTime": "2019-06-25 16:35:25"
}
]
}
通过java流就可以很方便的对数据进行分组和过滤。
public Map<String, Map<String, List<ProcessParameterCompleteDTO>>> listOutLimit(String startTime, String endTime) {
List<ProcessParameterCompleteDTO> processParameterEntities = dao.listOutLimit(startTime, endTime);
Map<String, Map<String, List<ProcessParameterCompleteDTO>>> outLLimitMap = processParameterEntities.stream().collect(
groupingBy(ProcessParameterCompleteDTO::getDeviceName,
groupingBy(ProcessParameterCompleteDTO::getName)));
return outLLimitMap;
}
4 新的日期和时间API
Java 8之前的时间日期的API非常的不理想,如DateFormat不是线程安全的,Date非常难用不说,Date和Calendar的类是可变的,所以也不是线程安全的。所以Joda Time在Java日期/时间需求中扮演了高质量替换的重要角色。java 8再java.time中整合了很多Joda-Time的特性。Java 8支持如下类:
- LocalDate: 不可变对象,提供简单的日期
- LocalTime: 表示1天中的时间
- LocalDateTime: 日期和时间的合体
- Instant:机器的日期和时间格式。
- Duration:用来表示对象间的持续时间
- Period: 表示时间间隔
我们分表时按照时间分表的,通过Java 8的LocalDateTime很方便的进行时间的加减(如minusHours)。也可以很方获取年和月等(getYear,getMonth)。
public String doSharding(final Collection<String> tableNames, final PreciseShardingValue<Timestamp> shardingValue) {
Timestamp acquisition_time = shardingValue.getValue();
LocalDateTime localDateTime = acquisition_time.toLocalDateTime().minusHours(offset);
/*
* 按照季度分表, 工作班次是有偏移的, 需要将同一个班次放在一张表中,便于分析和查询
* */
String tableName =shardingValue.getLogicTableName() + "_" +
localDateTime.getYear() + "_" +
((localDateTime.getMonth().getValue() - 1) / 3 + 1);
return tableName;
}