JAVA 8 新特性
JAVA 8 新特性
一、Lambda 表达式
四个内置的接口
函数式接口 只有一个方法的接口
Consumer
属于函数式接口,只有一个accept 方法
接收一个参数无返回值
Predicate
接收一个泛型,返回 boolean
Function
接收两个,一个是入参,一个是返回值
Supplier
传入一个参数,返回一个对象
二、stream 流
1. 获取流
1)集合类 xxx.stream()
2)Arrays
Object[] objects={1,2,3,4,5,6};
Stream stream = Arrays.stream(objects);
2. 中间操作
1.1)map 把对应的操作应用到 流里面的每一个对象上
/*
给定一个数字列表,返回平方列表
*/
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collectList = integerList.stream()
.map(x -> x = x * x)
.collect(Collectors.toList());
System.out.println(collectList);
1.2)map 提取对象里面的信息
示例
数据
Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
List<Transaction> transactionList = Arrays.asList(
new Transaction(brian, 2011, 300),
new Transaction(raoul, 2012, 1000),
new Transaction(raoul, 2011, 400),
new Transaction(mario, 2012, 710),
new Transaction(mario, 2012, 700),
new Transaction(alan, 2012, 950)
);
测试示例
@Test
public void test08() {
//提取所有交易员的名字,去除重复
transactionList.stream()
.map(Transaction::getTrader)
.map(Trader::getName)
.distinct()
.forEach(System.out::println);
}
解析
第一次 stream 之后,流里面是一个个的Transaction 对象,map 之后,流里面是一个个的Trader对象,再次map之后,是一个个的String ,可能有重复的,所以使用 去重
最终得到所有的交易员的姓名
2)filter 过滤
示例 过滤,只留下 大于 3 的数字
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
integerList.stream()
.filter(x->x>3)
.forEach(System.out::println);
3)skip()
跳过前面的几个
4)distinct() 去重
5)sorted(),默认是自然排序,可以定义排序规则
3. 终止操作
1)分组,根据条件,把流中的数据,拆分成不同的组
数据如下
List<Employee> employeeList = Arrays.asList(
new Employee(101, "张三", 10, "1111.0", Status.FREE),
new Employee(102, "李四", 20, "2222.0", Status.FREE),
new Employee(104, "田七", 30, "4444.0", Status.VOCATION),
new Employee(103, "王五", 30, "3333.0", Status.FREE),
new Employee(105, "天珩", 50, "5555.0", Status.FREE),
new Employee(106, "珩媛", 60, "6666.0", Status.VOCATION),
new Employee(105, "天珩", 40, "9999.0", Status.BUSY),
new Employee(105, "天珩", 40, "7777.0", Status.BUSY)
);
测试代码
逻辑:根据年龄把员工分三个组 青年,中年,老年
@Test
public void test08() {
//分组
ConcurrentMap<Status, Map<String, List<Employee>>> groups = employeeList.stream()
.collect(Collectors.groupingByConcurrent(Employee::getStatus, Collectors.groupingBy(employee -> {
if (employee.getAge() <= 35) {
return "青年";
} else if (employee.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
groups.forEach((key,value)->{
System.out.println("key is "+key+"\nvalue is "+value);
});
}
输出的结果
2)分区
可以分true false 两个区
@Test
public void test09() {
//分区
Map<Boolean, List<Employee>> partitioningByAge = employeeList.stream()
.collect(Collectors.partitioningBy(employee -> employee.getAge() > 35));
partitioningByAge.forEach((key,value)-> System.out.println("key is "+key+"\nvalue is "+value));
}
3) count()
返回一个 Long 类型数据,流的对象个数
4)收集
ArrayList collect1 = employeeList.stream() .collect(Collectors.toCollection(ArrayList::new));
5)reduce
4)max
5)min
全部匹配 allMatch
至少一个匹配 anyMatch
没有匹配的元素,返回true,否则false noneMatch
三、ForkJoin
工作窃取模式
原理
会划分多个工作线程,每个线程独立的并行工作,当某线程已经完成,还有别的线程没有完成时,会取得其余线程的末尾工作,继续执行,这样中分的利用 CPU 的每个核的资源
传统的线程会等待最慢的线程执行完成之后,整个工作才结束,ForkJoin会利用工作窃取,分担最慢的工作。
示例 累加器 加到10亿
第一个模块,拆分工作的算法
继承 RecursiveTask 实现compute()方法,有返回值
继承 RecursiveAction实现compute()方法,无返回值
public class ForkJoinCal extends RecursiveTask<Long> {
/**
* RecursiveAction
* protected abstract void compute(); 没有返回值
*
*/
private Long start;
private Long end;
private static final Long THRESODLD=10000L;
public ForkJoinCal(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
Long length=end-start;
if (length<=THRESODLD){
Long sum=0L;
for (Long i=start;i<=end;i++){
sum+=i;
}
return sum;
}else {
Long middle = (start + end) / 2;
ForkJoinCal left=new ForkJoinCal(start ,middle);
//拆分子任务,压入栈
left.fork();
ForkJoinCal right = new ForkJoinCal(middle + 1, end);
//拆分子任务,压入栈
right.fork();
return left.join()+right.join();
}
}
}
第二个模块,使用
@Test
public void test01(){
Instant start=Instant.now();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> forkJoinTask=new ForkJoinCal(0L,1000000000L);
Long sum = forkJoinPool.invoke(forkJoinTask);
System.out.println("this is sum : "+sum);
}
运行时,可以查看 CPU 状态,可以看到 利用率非常高
并行流。实现累加
//并行流
Long reduceSum = LongStream.range(0, 100000001L)
//并行流
.parallel()
.reduce(0, Long::sum);
底层使用的也是 fork join 机制,效率更高
四、Optional
提供了新的接口,确保快速定位到null
- empty() 创建一个空对象,对象不是null 只是对象的属性都是null
- of()创建一个可以为null 的对象
- ofNullable()创建对象,调用的是empty()和 of()
- isPresent()判断对象是否为null ,null 返回false orElse(T t)如果对象为null,则创建一个默认的对象 t
- orElseGet 可以 自己定义构造一个默认的对象
五、新的时间API
Instant
LocalDateTime
Duration
Period