Java 8 新特性
一、 接口
在java8 中,接口中引入了新的关键字default和static,通过使用default修饰方法,可以让我们在接口中定义具体的方法实现,也可使用static关键字来定义接口方法。
public interface InterClass {
String test1(String str);
default String test2(String str){
return "test2:" + str;
}
static String test3(String str){
return "test3:" + str;
}
}
二、Lamdba表达式
Lambda表达式的语法格式如下:
(params) -> expression 或 (params) -> {statements;}
Lambda(兰布达)表达式,是推动Java 8 发布的最重要的新特性,这意味着Java也开始承认了函数式编程。函数式编程的一个特点就是允许把函数本身作为参数传入另一个函数,还允许返回一个函数。使用Lambda表达式可以使代码变的更加简洁紧凑。
下面代码解释了什么是函数式接口编程:
/**
* 函数式接口
* 函数式接口是值仅仅只包含一个抽象方法的接口(可以有多个default和static方法),
* 每一个Lambda表达式都会匹配到这个方法。
* jdk1.8 提供了 注解@FunctionalInterface来定义函数式接口
*/
@FunctionalInterface
public interface FunInterface {
String test1(String str);
/**如果包含多个抽象接口,编译器会报错
* 如在定义一个抽象方法 String test2(String str);
* 但是可以定义任意多个的 default方法和 static方法
*/
default String test3(String str){
return "test3:" + str;
}
default String test4(String str){
return "test4:" + str;
}
static String test5(String str){
return "test5:" + str;
}
static String test6(String str){
return "test6:" + str;
}
}
测试:
public static void main(String args[]) {
FunInterface funInterface = str -> "这是一个Lambda表达式";
System.out.println(funInterface.test1(""));
System.out.println(funInterface.test3("调用default方法"));
System.out.println(FunInterface.test5("调用static方法"));
}
Lambda表达式的重要特征:
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
- 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
- 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
- 可选的返回关键字:如果主体只有一个表达式返回值,则编译器会自动返回值,大括号需要指定表达式返回了一个数值。
Lambda表达式的变量作用域:
- Lambda表达式只能引用标记为 final的外层局部变量。
- Lambda表达式的局部变量可以用声明为final,但是必须在后面的代码中不能进行修改。
- Lambda表达式中不允许声明一个与局部变量同名的参数或局部变量。
三、方法引用
Jdk1.8 提供了另一种调用方式一对冒号( :: ),当你需要使用方法引用时,目标引用放在分隔符 :: 前,方法的名称放在后面,及 ClassName::methodName,注意:调用构造函数引用为ClassName::new 。
public class TestMethodAddr {
@FunctionalInterface
public interface FunInterface {
TestMethodAddr getTestMethodAddr(String a,String b);
}
private String a;
private String b;
public TestMethodAddr(String a,String b){
this.a = a;
this.b = b;
}
public String addStr(){
return a + b;
}
public String append(String c){
return a + "," + b + "," + c;
}
public static void main(String[] args){
FunInterface funInterface = TestMethodAddr::new;
TestMethodAddr test = funInterface.getTestMethodAddr("A", "B");
System.out.println(test.addStr());
System.out.println(test.append("C"));
}
}
四、Stream
Java 8 中添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。可以将Stream看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,如排序、筛选、聚合运算等。
Stream是一个来自数据源的元素队列并支持聚合操作。Stream提供了内部迭代的方法,通过 访问者模式(Visitor) 实现(iterator、foreach为外部迭代)。
- 数据源:stream流的产生对象,可以是集合、数组、IO channel等。
- 元素:指特定类型的对象,形成一个对象。
- 聚合操作:类似sql语句一样的操作,比如filter、map、limit、find、sorted等。
- 生成流stream:使用方法stream() 为集合创建串行流,parallelStream() 为集合创建并行流。
- forEach:stream提供了新的方法 forEach来迭代流中的每个数据。如:
List list = Arrays.asList(1,2,3,4,5);
list.stream().forEach(System.out::println);
- map:stream提供了map方法来用于映射每个元素到对应的结果。如:
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().map(i -> i + i);
list.stream().map(i -> i + i).forEach(System.out::println);
- filter: filter方法用于通过设置条件过滤出元素,返回满足条件的元素。如:
List<Integer> list = Arrays.asList(1,2,3,4,5);
// 过滤大于3的元素
list.stream().filter(i -> i > 3).forEach(System.out::println);
- limit:limit方法用于获取指定数量的流。如:
List<Integer> list = Arrays.asList(1,2,3,4,5);
// 获取前 3个stream流
list.stream().limit(3).forEach(System.out::println);
- Sorted:sorted方法用于对流进行排序。如:
List<Integer> list = Arrays.asList(5,2,3,1,4);
// 将list中的元素从小到大进行排序
list.stream().sorted((a,b) -> (a > b ? 1 : -1)).forEach(System.out::println);
java集合Stream常用方法:
List<String> list1 = Arrays.asList("kd", "id", "qw", "xw", "ae",
"de", "ef", "aaaaaa", "bbbbb");
List<String> list2 = Arrays.asList("od", "ps", "sk", "we", "rx",
"mx", "no", "aaaaaa", "bbbbb");
// concat:合并两stream
Stream.concat(list1.stream(), list2.stream()).map(str -> str + "_").forEach(System.out::print);
System.out.println("\n----------------------");
// distinct:stream中元素去重
Stream.concat(list1.stream(), list2.stream()).distinct().map(str -> str + "_").forEach(System.out::print);
System.out.println("\n----------------------");
// filter:根据指定条件进行筛选过滤,留下满足条件的元素
System.out.println("\n----------------------");
List<String> list3 = Arrays.asList("aa", "bb", "cc", "dd", "bb", "a");
list3.stream().distinct().filter(str -> str.length() > 1).map(s -> s + "_").forEach(System.out::print);
// map:将stream中的元素进行映射转换
System.out.println("\n----------------------");
list3.stream().map(String::toUpperCase).forEach(System.out::print);
list3.stream().mapToInt(String::length).forEach(System.out::print);
// peek:生成一个相同的Stream,并提供一个消费函数,当新Stream中的元素被消费(执行操作)时,该消费函数会在此之前执行
System.out.println("\n----------------------");
list3.stream().peek(s -> {
s = "xxxxaaaa";
System.out.print(" 大写:" + s.toUpperCase());
}).forEach(s -> System.out.println(" 小写:" + s));
// skip:跳过前N个元素,取剩余元素,如果没有则为空Stream
System.out.println("\n----------------------");
list3.stream().skip(2).peek(s -> System.out.print(" 大写:" + s.toUpperCase())).forEach(s -> System.out.println(" 小写:" + s));
// sorted:对stream元素进行排序
System.out.println("\n----------------------");
list3.stream().sorted((s1, s2) -> s2.length() - s1.length()).forEach(System.out::print);
// limit:限制返回前N个元素,与SQL中的limit相似
System.out.println("\n----------------------");
list3.stream().skip(2).limit(20).forEach(System.out::print);
// allMatch:判断stream中的所有元素是否满足指定条件。全部满足返回true
System.out.println("\n----------------------");
System.out.println(list3.stream().limit(2).allMatch(s -> s.length() == 2));
// anyMatch:判断stream中的元素至少有一个满足指定条件。如果至少有一个满足,返回true
System.out.println(list3.stream().anyMatch(s -> s.length() == 1));
// noneMatch:判断stream中是否所有元素都不满足指定条件。如果都不满足,返回true
System.out.println(list3.stream().noneMatch(s -> s.length() == 3));
五、日期时间
新增各种日期时间处理类。
LocalDate为日期处理类、LocalTime为时间处理类、LocalDateTime为日期时间处理类。
DateTimeFormatter格式化日期时间处理类。