【十】Java8新特性
2018-05-28 本文已影响0人
吴里庆庆
一、主要内容
- 1.Lambda表达式
- 2.函数式接口
- 3.方法引用和构造器引用
- 4.Stream API
- 5.接口中的默认方法与静态方法
- 6.新时间日期API
- 7.其他新特性
1.1 Lambda表达式
注:不支持Lambda表达式可参考https://blog.csdn.net/weixin_39800144/article/details/78500449?locationNum=8&fps=1进行设置。
1.1.1 Lambda表达式语法
/*
* 一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符
* 箭头操作符将 Lambda 表达式拆分成两部分:
*
* 左侧:Lambda 表达式的参数列表
* 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
*
* 语法格式一:无参数,无返回值
* () -> System.out.println("Hello Lambda!");
*
* 语法格式二:有一个参数,并且无返回值
* (x) -> System.out.println(x)
*
* 语法格式三:若只有一个参数,小括号可以省略不写
* x -> System.out.println(x)
*
* 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
* Comparator<Integer> com = (x, y) -> {
* System.out.println("函数式接口");
* return Integer.compare(x, y);
* };
*
* 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
* Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
*
* 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
* (Integer x, Integer y) -> Integer.compare(x, y);
*
* 上联:左右遇一括号省
* 下联:左侧推断类型省
* 横批:能省则省
*
* 二、Lambda 表达式需要“函数式接口”的支持
* 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰
* 可以检查是否是函数式接口
*/
//Lambda 表达式
@Test
public void test6(){
List<Employee> list = filterEmployee(emps, (e) -> e.getAge() <= 35);
list.forEach(System.out::println);
System.out.println("------------------------------------------");
List<Employee> list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
list2.forEach(System.out::println);
}
1.2 四大内置核心函数式接口
- Java8 内置的四大核心函数式接口
Consumer<T> : 消费型接口
void accept(T t);
Supplier<T> : 供给型接口
T get();
Function<T, R> : 函数型接口
R apply(T t);
Predicate<T> : 断言型接口
boolean test(T t);
1.3方法引用与构造器引用
/*
* 一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用
* (可以将方法引用理解为 Lambda 表达式的另外一种表现形式)
*
* 1. 对象的引用 :: 实例方法名
*
* 2. 类名 :: 静态方法名
*
* 3. 类名 :: 实例方法名
*
* 注意:
* ①方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
* ②若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
*
* 二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!
*
* 1. 类名 :: new
*
* 三、数组引用
*
* 类型[] :: new;
*
*
*/
1.4 Stream API
//Stream API
@Test
public void test7(){
emps.stream()
.filter((e) -> e.getAge() <= 35)
.forEach(System.out::println);
System.out.println("----------------------------------------------");
emps.stream()
.map(Employee::getName)
.limit(3)
.sorted()
.forEach(System.out::println);
}
2 Stream
注:此节前面几小节还在整理中....
2.5 查找与匹配
测试集合:
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 100.00),
new Employee(101, "张三", 18, 200.00),
new Employee(103, "王五", 28, 100.00),
new Employee(104, "赵六", 8, 150.00),
new Employee(104, "赵六", 28, 200.00),
new Employee(105, "田七", 38, 150.00)
);
public void test1() {//查找与匹配
//排序
emps.stream().sorted(Comparator.comparingDouble(Employee::getSalary))
.forEach(System.out::println);
System.out.println("-------------------------------1---------------------");
//找到最有钱的员工
Optional<Employee> one = emps.stream()//.sorted((x,y)->Double.compare(x.getSalary(),y.getSalary()))
.max(Comparator.comparingDouble(Employee::getSalary));
System.out.println(one.get());
System.out.println("-------------------------------2---------------------");
//找到最穷的员工的工资是多少
Optional<Double> min = emps.stream().map(Employee::getSalary).min(Double::compare);
System.out.println(min.get());
System.out.println("-------------------------------3---------------------");
//个数
long count = emps.stream().filter((x) -> x.getSalary() > 50).count();
System.out.println(count);
}
2.6 归约与收集
- 2.6.1 归约
@Test
public void test2() {//归约
System.out.println("----------------------(1)测试归约---------------------");
List<Integer> list = Arrays.asList(1, 2, 3);
Integer a = 1;
Integer sum = list.stream().reduce(a, (x, y) -> x + y);
/* Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);
System.out.println(reduce.get());*/
//先把a作为x,再从集合中取出第一个元素1作为y,
// 把它们相加的结果再作为x,再从集合中取出第2个元素作为y依次类推相加的结果就是sum.
System.out.println(sum);
System.out.println("----------------------(2)测试员工工资总和---------------------");
Optional<Double> salarys = emps.stream().map(Employee::getSalary).reduce(Double::sum);
//为什么这里返回的是Optional?因为员工的工资为空,而上面第一个例子中有个起始值a所以它不为空
System.out.println(salarys.get());
}
- 2.6.2 收集
@Test
public void test3() {//收集
System.out.println("----------------------(1)测试收集---------------------");
//放到list中
List<String> collect = emps.stream().map(Employee::getName).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("----------------------(2)测试收集set去重---------------------");
//放到set中 去下重
Set<String> namesDistinct = emps.stream().map(Employee::getName).collect(Collectors.toSet());
namesDistinct.forEach(System.out::println);
//想放哪就放哪
System.out.println("----------------------(3)测试收集hashset---------------------");
HashSet<String> hashNames = emps.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
hashNames.forEach(System.out::println);
System.out.println("----------------------(4)测试收集 获取总数和平均值 ---------------------");
//总数
Long num = emps.stream().collect(Collectors.counting());
System.out.println(num);
//平均值
Double averageSalary = emps.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(averageSalary);
//工资总和
Double sumSalary = emps.stream().collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sumSalary);
//获取最大工资的员工
Optional<Employee> maxEmployee = emps.stream().collect(Collectors.maxBy((x, y) -> Double.compare(x.getSalary(), y.getSalary())));
System.out.println(maxEmployee.get());
//获取最小工资值
Optional<Double> minSalary = emps.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compare));
System.out.println(minSalary.get());
}
- 2.6.3 收集-组函数
@Test
public void test3_1() {//组函数
DoubleSummaryStatistics collect = emps.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(collect.getAverage());//平均值
System.out.println(collect.getSum());//员工工资总数
System.out.println(collect.getCount());//员工数
System.out.println(collect.getMax());//最大工资数
System.out.println(collect.getMin());//最小工资数
}
- 2.6.4 收集-分组
@Test
public void test4() {
//收集--分组
Map<String, List<Employee>> collect = emps.stream().collect(Collectors.groupingBy(Employee::getName));
// map没有foreach
//System.out.println(collect);
//收集--多级分组
Map<String, Map<Integer, List<Employee>>> collect1 = emps.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.groupingBy(Employee::getAge)));
System.out.println(collect1);
Map<String, Map<String, List<Employee>>> collect2 = emps.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.groupingBy((x) -> {
if (x.getAge() < 18) {
return "少年";
} else {
return "成年";
}
})));
System.out.println(collect2);
}
- 2.6.5 收集-分区
@Test
public void test5() {
//收集--分区
Map<Boolean, List<Employee>> collect = emps.stream().collect(Collectors.partitioningBy((e) -> e.getSalary() > 120.0));
//满足工资大于120的分一个区,其他的分在另一区
System.out.println(collect);
}
- 2.6.6 收集-连接
@Test
public void test6(){
String collect = emps.stream().map(Employee::getName)
// .distinct()//去重
// .collect(Collectors.joining());
//.collect(Collectors.joining("->"));//加上符号 输出 李四->张三->王五->赵六->赵六->田七
.collect(Collectors.joining("->","(",")"));//加上首尾 输出 (李四->张三->王五->赵六->赵六->田七)
System.out.println(collect);
}