Java 8 新特性简介
速度更快
- 修改底层数据结构:如HashMap(数组-链表-红黑树),HashSet,ConcurrentHashMap(CAS算法)
- 修改垃圾回收机制:取消堆中的永久区(PremGen)->回收条件苛刻,使用元空间(MetaSpace)->直接使用物理内存->加载类文件
代码更少
(增加了新的语法Lambda
表达式)- 强大的
Stream API
- 便于
并行
- 最大化减少空指针异常
Optional
容器类
lambda
最主要的使用场景:
runnable
、comparetor
等;map()
,reduce()
等;filter()
;lambda
的语法:
(params) -> expression
;(params) -> statement
;(params) -> {statements}
() -> System.out.println("Hello Lambda Expressions")
;(int even, int odd) -> even + odd
lambda
替代匿名类1实现比较器:
before java8:
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;//降序
}
};
TreeSet treeSet = new TreeSet(comparator);
或者直接将比较器写在需要比较器的位置:
List list = new ArrayList();
list.add(1);
list.add(2);
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;//降序
}
});
System.out.println(list);//[2,1]
java8:
在需要匿名类的地方,即通过new接口再实现的地方,都可以使用lambda
:
实现比较器只需要:
Comparator<Integer> comparator1 = (x,y)->y-x;//降序
or:
Comparator<Integer> comparator2 = (x,y)->Integer.compare(y,x);//降序
TreeSet<Integer> treeSet = new TreeSet<>(comparator1);
treeSet.add(1);
treeSet.add(2);
System.out.println(treeSet);//[2,1]
lambda
替代匿名类2实现线程
before java8:
@Test
public void threadTest(){
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("new thread..."+Thread.currentThread().getName());
//Thread-0
}
}).start();
System.out.println(Thread.currentThread().getName());//main
}
以上代码有两个线程,Thread-0
和main
(都为默认名)。 Thread方法需要一个线程实例,传统方法仍然是new接口的实现来实现。
java8:
替代匿名类,需要关注的是:
是对接口中待实现方法的实现,因此要对应到原方法中的参数
new Thread(()-> System.out.println(Thread.currentThread().getName())).start();
//Thread-1
上述run方法中无参数,因此lambda
中只需()
即可
lambda
替代匿名类的综合示例对以下员工信息进行年龄和薪水过滤
@Setter @Getter @AllArgsConstructor @ToString
public class Employee {
private int age;
private int salary;
}
通常有的方法有:
① 普通过滤方法(缺点:扩展性差)
public List<Employee> filterEmplyeesByAge(List<Employee> list){...}
public List<Employee> filterEmplyeesBySalary(List<Employee> list){...}
public List<Employee> filterEmplyeesByOther(List<Employee> list){...}
当需要增加过滤条件时,就需要写很多的过滤方法。为了改进,我们可以只写一个过滤方法,传入过滤添加即可。如下。
优化1:
②策略设计模式
我们需要写一个过滤接口,再写实现类。用于识别不用的过滤方法。
(A) 过滤接口:
public interface MyPredicate<T> {
boolean filter(T t);
}
其中,T
表示要过滤的类型,如果该接口不再用于其他类的过滤,其实这里可以写死Employee
。
(B) 接口的实现类
public class EmployeeSalaryFilter implements MyPredicate<Employee> {
@Override
public boolean filter(Employee emp) {
return emp.getSalary()>2000;
}
}
这里是一个过滤工资的类。是通过实例作为参数传入到过滤方法的。通用过滤方法如下:
(C ) 通用过滤方法
public static List<Employee> filterEmployee(List<Employee> emps,MyPredicate<Employee> myPredicate){
List<Employee> res = new ArrayList<>();
for (Employee emp : emps) {
if(myPredicate.filter(emp)){
res.add(emp);
}
}
return res;
}
测试:
@Test
public void employeeTest(){
Employee e1=new Employee(20,1800);
Employee e2=new Employee(30,2800);
Employee e3=new Employee(40,3800);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
//1.策略方法过滤
List<Employee> emps = Employee.filterEmployee(employees,new EmployeeSalaryFilter());
System.out.println(emps);
//[Employee(age=30, salary=2800), Employee(age=40, salary=3800)]
}
分析:上述策略模式
优点是:
缺点是:
优化2:
对于每次新增过滤条件时,都要写实现类,来实现接口,比较繁琐,可能要实现很多个接口:
public class EmployeeSalaryFilter implements MyPredicate<Employee> {...}
public class EmployeeAgeFilter implements MyPredicate<Employee> {...}
public class EmployeeOtherFilter implements MyPredicate<Employee> {...}
...
单独创建类是非常多余的,因此优化方式是:匿名内部类。
@Test
public void employeeTest(){
Employee e1=new Employee(20,1800);
Employee e2=new Employee(30,2800);
Employee e3=new Employee(40,3800);
List<Employee> employees = new ArrayList<>();
employees.add(e1);
employees.add(e2);
employees.add(e3);
//1.策略方法过滤
List<Employee> emps = Employee.filterEmployee(employees,new EmployeeSalaryFilter());
System.out.println(emps);//[Employee(age=30, salary=2800), Employee(age=40, salary=3800)]
//2.上述方式使用匿名内部类改进
List<Employee> emps2 = Employee.filterEmployee(employees, new MyPredicate<Employee>() {
@Override
public boolean filter(Employee employee) {
return employee.getSalary()>2000;
}
});
System.out.println(emps2);
//[Employee(age=30, salary=2800), Employee(age=40, salary=3800)]
}
分析:上述匿名内部类,不需要额外再写实现类,再需要使用的时候,直接用内部类实现。
优化3:
lambda
//3.lambda
List<Employee> emps3 = Employee.filterEmployee(employees,(e)->e.getSalary()>2000);
emps3.forEach(System.out::println);
优化4:
stream api
//4.stream() api
List<Employee> emps4 = employees
.stream()
.filter(e->e.getSalary()>2000)
.collect(Collectors.toList());
System.out.println(emps4);
//[Employee(age=30, salary=2800), Employee(age=40, salary=3800)]
System.out.println("------------------");
employees.stream()
.map(Employee::getAge)
.forEach(System.out::println);