JDK 8 新特性
Java 5 中的相关特性
部分常用语法在 Java 5 中已经引入,学习 JDK 8 特性时经常会一起使用。
枚举
枚举是一种特殊类型,用于表示一组固定的常量。枚举常量必须写在枚举体的最前面。
public enum Week {
MON("星期一"),
TUE("星期二"),
WED("星期三"),
THU("星期四"),
FRI("星期五"),
SAT("星期六"),
SUN("星期日");
private final String chineseName;
Week(String chineseName) {
this.chineseName = chineseName;
}
public String getChineseName() {
return chineseName;
}
}枚举常量在类型定义完成后不能随意增加或删除。通常把枚举对象的属性设计为不可变属性。
可变参数
可变参数允许调用方法时传入数量不定的同类型实参。一个方法最多只能有一个可变参数,并且它必须位于参数列表的最后。
public class Test {
public static void method(String text, int... numbers) {
System.out.println(text);
for (int number : numbers) {
System.out.println(number);
}
}
public static void main(String[] args) {
method("abc", 1, 2, 3, 4);
}
}在方法内部,可变参数按照数组使用。
JDK 8 的主要特性
接口默认方法和静态方法
JDK 8 允许接口定义默认方法和静态方法。默认方法使用 default 修饰,主要用于在扩展接口时兼容已有实现类。
public interface ITest {
void method();
default void method1() {
System.out.println("默认方法");
}
static void method2() {
System.out.println("静态方法");
}
}函数式接口
只有一个抽象方法的接口称为函数式接口。函数式接口可以包含默认方法和静态方法,因为它们不属于抽象方法。
@FunctionalInterface 注解用于校验接口是否满足函数式接口的要求。
@FunctionalInterface
public interface ITest {
void method();
default void method1() {
System.out.println("默认方法");
}
}
Lambda 表达式
Lambda 表达式用于简洁地表示函数式接口抽象方法的实现,其基本结构为:
(参数列表) -> { 方法体 }
例如,创建线程时可以直接提供 Runnable 的实现:
new Thread(() -> {
System.out.println("执行 run 方法");
}).start();
参数类型通常可以由编译器推断。当方法体只有一条语句时,可以省略大括号;如果唯一语句是返回表达式,还可以同时省略 return。
Arrays.sort(strings, (s1, s2) -> s1.length() - s2.length());
Lambda 表达式写法简洁,但它必须出现在需要函数式接口对象的位置。
方法引用
当已有方法能够完成 Lambda 表达式所描述的操作时,可以使用方法引用。常见形式如下:
类名::静态方法
类名::实例方法
对象::实例方法
类名::new
方法引用能否使用,取决于目标函数式接口的抽象方法参数和返回值是否与被引用方法兼容,方法名不要求相同。
List<String> list = new ArrayList<>();
Collections.addAll(list, "ab", "cd", "ef");
list.forEach(value -> System.out.println(value));
list.forEach(System.out::println);
list.forEach(Test::upperPrintln);
public class Test {
public static void upperPrintln(String value) {
String result = String.valueOf(value.charAt(0)).toUpperCase()
+ value.substring(1);
System.out.println(result);
}
}
Stream 流
Stream 用于对数据序列执行过滤、映射、排序、聚合等操作。它不会直接存储数据,通常以集合或数组作为数据源。
遍历元素
forEach() 是终止操作,用于消费流中的元素。
List<Integer> list = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
list.stream().forEach(System.out::println);
list.parallelStream().forEach(System.out::println);
并行流的输出顺序不一定与原集合一致。
映射元素
map() 把每个元素转换为另一个值,并生成新的流。
list.stream()
.map(number -> number * 2)
.forEach(System.out::println);
过滤和截取
filter() 根据条件保留元素,limit() 限制结果数量。操作顺序不同,结果也可能不同。
list.stream()
.limit(3)
.filter(number -> number > 2)
.forEach(System.out::println);
list.stream()
.filter(number -> number > 2)
.limit(3)
.forEach(System.out::println);排序和去重
sorted() 用于排序,distinct() 用于去重。
list.stream()
.sorted()
.distinct()
.forEach(System.out::println);
收集结果
collect() 可以把流处理结果收集到新集合或字符串中。
List<Integer> oddNumbers = list.stream()
.filter(number -> (number & 1) == 1)
.collect(Collectors.toList());
System.out.println(oddNumbers);
List<String> words = Arrays.asList("a", "b", "c");
String result = words.stream()
.collect(Collectors.joining("-"));
System.out.println(result);统计数量
count() 返回流中元素的数量。
long count = list.stream()
.filter(number -> number > 2)
.count();
System.out.println(count);
喜欢的话,留下你的评论吧~