JDK8的特性
在JDK8中新增一些特殊功能,一般开发时方便使用, 其中最主要的功能如下
1、接口的默认函数
public interface MyInterface {
public default void defaultMethods(){
System.out.println("这是一个接口的默认方法。");
// 静态方法可以在default方法中调用
staticMethods();
}
public void service();
public static void staticMethods(){
System.out.println("这是接口的静态方法");
}
}
public static void main(String[] args) {
// 创建匿名内部类的方式
MyInterface my = new MyInterface() {
@Override
public void service() {
System.out.println("service方法.....");
}
};
my.defaultMethods();
//通过接口名 调用静态方法
MyInterface.staticMethods();
}
2、Lambda表达式
JDK8中支持一种对方法调用的 简写方式 ,也是一种特殊写法
语法: ([形参名]) ->{ 方法的实现}
这个接口中有且只有一个方法,并对方法实现
原始代码
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
// 降序
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1); //降序
}
})
由于JDK能识别sort的参数二是Comparator , 并Comparator是函数式接口(一个接口中有且只有一个方法。),实现的一定是唯一的方法名, 所有这里方法名和返回值也省略, 它的简写方式
// 使用lambda表达式 ([形参])->{方法体}
Collections.sort(list ,(String o1,String o2)->{
return o2.compareTo(o1);
});
由于形参的数据类与集合的元素类型一致,这里的形参类型也省略 、return也省略
// 最精简的Lambda
Collections.sort(list ,(o1,o2)->o2.compareTo(o1));
3、函数式接口
函数式接口主要用于满足前面Lambda表达式的语法的使用。 在一个接口中 有且只有一个方法的接口称为 “函数式接口” ,
如何将一个接口定义为函数式接口呢? 在接口上增加注解 “@FunctionalInterface”
package com.j2008.functionalFun;
@FunctionalInterface // 该注解的意义在于 约束接口只能由一个方法
public interface ConverterInterface<T> {
public String convertStr(T t);
}
//传统写法
ConverterInterface<Integer> con = new ConverterInterface<Integer>() {
@Override
public String convertStr(Integer o) {
return o.toString();
}
};
String ss = con.convertStr(100);
System.out.println(ss);
//使用 lambda表达式写法
ConverterInterface<Date> cons = (o)->o.toLocaleString();
String s = cons.convertStr(new Date());
System.out.println(s);
4、方法和构造器的引用
4.1 方法的引用
在以上接口函数中 这个convert方法的实现 对于java.lang包中是存在相同的方法的,所以 convert的实现可以直接引用已有静态方法 Integer.valueOf 或者 Integer.parseInt
以上代码的实现可以改成这样 :
语法: 类名 :: 静态方法名
@FunctionalInterface
public interface Convert<F,T> {
//将F转成T
public T convertType (F f);
}
public static void main(String[] args) {
// 原始使用lambda表达式 可以这样写
// 把字符串转成 Integer
Convert<String ,Integer> con = (f)->{
return Integer.parseInt(f);
};
Integer n = con.convertType("888");
// 在lambda基础上,如果实现的方法 已存在,则可直接调用 类名::方法名
Convert<String ,Integer> con2 = Integer::valueOf;
Convert<String ,Integer> con3= Integer::parseInt;
//调用方法实现
Integer n2 = con2.convertType("123");
int n3 = con3.convertType("555");
}
4.2 构造器的引用
当方法的实现 是构造器时,可直接引用构造器
语法: 类名::new
@FunctionalInterface
public interface StudentFactory<T> {
// 参数是创建对象时 的 属性
public T create(int id ,String name);
}
public class Student {
private int sid;
private String sname;
public Student(int sid, String sname) {
this.sid = sid;
this.sname = sname;
}
}
public static void main(String[] args) {
//使用Lambda实现 函数接口的方法
StudentFactory<Student> factory = (id,name)->{
return new Student(id ,name);
};
Student stu1 = factory.create(1001,"张三丰");
System.out.println(stu1);
// 以上写法可以直接换成 引用构造器方式
StudentFactory<Student> factory1 = Student::new;
//创建
Student stu2 = factory1.create(1002,"张无忌");
System.out.println(stu2);
}
5、集合的流式处理
在JDK8以后,提供对集合的流式操作,对集合的元素可以向“流水”一样,依次方便,遍历,排序等,它是“不可逆的”(访问后面元素之后不能再次返回前面元素 ) , 根据流的处理方式不同,可以分为 串行流和并行流, 串行流表示同一时间只能有一个流式操作,而并行流可以有多个流式操作。
流返回的结果包括中间操作和 最终操作
中间操作:它的返回值依然是 流对象 ,例如 排序、过滤、去重
最终操作: 返回值是特定的结果类型 ,例如 遍历,取最大值,最小值或返回新的集合
常用方法:
stream() :将一个集合流式化
filter(): 按条件过滤,里面使用lambda表达式
sort(): 排序集合元素
distinct: 过滤重复元素
reduce() : 将集合的所有元素累加或拼接
map(); 映射一个新的集合 对集合元素变更输出
collect():返回一个新集合
max() min():返回集合最大值或最小值
get (): 获取集合计算的结果
public static void main(String[] args) {
List<Integer> list = new ArrayList();
for(int i = 0 ;i<7;i++){
list.add(i+1);
}
// 1、过滤 filter() 过滤掉偶数
list.stream().filter( param ->param%2==1 )
.forEach(System.out::println); //遍历元素
// 2、排序 sort() 降序
list.stream().sorted((o1,o2)->o2-o1).forEach(System.out::println);
// 3 map() 映射一个新的集合 , 如果是奇数 输出奇数 ,否则偶数
list.stream().map(
param -> param%2==1?"这个元素是奇数":"这是偶数"
).forEach(System.out::println);
list.add(1);
list.add(1);
System.out.println("去重元素");
// 4 distinct() 去除重复元素
list.stream().distinct().forEach(System.out::println);
// 5 reduce() 将集合的所有元素 累加(或拼接)
int sum = list.stream().reduce((o1,o2)->o1+o2).get();
System.out.println("总和:"+sum);
// 6 collect 返回一个新的集合
List<Integer> list2= list.stream().filter(param->param%2==1).collect(Collectors.toList());
System.out.println("遍历新集合");
list2.stream().forEach(System.out::println);
// 7、最大和最小
int max = list2.stream().max((o1,o2)->o1-o2 ).get();
System.out.println("最大值:"+max);
int min = list2.stream().min((o1,o2)->o1-o2 ).get();
System.out.println("最小值:"+min);
}