文章目录
一,介绍
JDK 1.8,即Java 8,是Oracle公司发布的Java平台的重要版本,其正式发布日期是2014年3月18日。这个版本包含了大量革新性的特性和改进,这些特性不仅增强了Java语言本身的表达力,同时也改善了开发者的编程体验。下面是关于JDK 1.8的一些主要特性的详细介绍:
-
Lambda表达式:
- Lambda表达式是一种轻量级的匿名函数,它们可以作为方法参数或者返回值,极大地简化了函数式编程模式在Java中的应用。Lambda表达式使得代码更加简洁和易于维护。
-
Stream API:
- Stream API是一个新的框架,它提供了高级抽象来进行集合类的操作,比如搜索、过滤、映射和排序等。Stream API的设计允许开发者利用现代多核硬件进行并行处理,而不需要关心线程管理和同步的问题。
-
新的日期和时间API:
- Java 8引入了新的日期时间API (
java.time
包),其中包括LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
等类。这些类设计得更为直观和易用,并且它们是不可变的,这意味着它们非常适合在并发环境中使用。
- Java 8引入了新的日期时间API (
-
默认方法和静态方法:
- 在接口中可以声明默认方法和静态方法,这为接口的实现者提供了默认的行为定义,同时保持了向后兼容性。静态方法则可以在不创建接口实例的情况下直接调用。
-
方法引用:
- 方法引用是Lambda表达式的补充,它提供了一种简洁的方式去引用现有的类方法或构造器,或者是特定对象的实例方法。
-
更好的类型推断:
- JDK 1.8中的类型推断机制得到了改善,这使得在创建泛型实例时可以省略类型参数,从而让代码更为清晰。
-
并行流:
- 并行流(Parallel Stream)允许自动利用多核心的计算能力,对数据进行高效并行处理。这有助于提高应用程序在多核处理器上的执行效率。
此外,JDK 1.8还包含了一些其他的改进,比如:
- 改进了类型注解,使得类型系统更为强大。
- 引入了Nashorn JavaScript引擎,它能够在Java平台上运行JavaScript脚本。
- 允许使用重复注解,这样就可以在同一位置多次应用相同的注解。
Lambda
Lambda 表达式简介
-
语法 :Lambda表达式的语法包括参数列表和Lambda体两部分。参数列表可以省略类型声明,Lambda体可以简化为单个表达式而无需大括号和
return
关键字(如果体内的确只有一条语句)。 -
函数式接口:Lambda表达式必须与函数式接口一起使用,后者是指仅有一个抽象方法的接口。Lambda表达式可以赋值给此类接口类型的变量或传递给期望该接口的方法。
-
方法引用:这是一种更简洁的方式,用于引用已有类或对象的方法或构造器。方法引用的语法为"对象或类名::方法名",适用于某些Lambda表达式场景。
Lambda 表达式的应用场景
-
集合操作 :Java 8的
Stream
API允许使用Lambda表达式来进行集合的过滤、映射、排序和聚合等操作。这极大地方便了集合数据的处理。 -
接口中的默认方法和静态方法 :Java 8允许在接口中定义默认方法(使用
default
关键字)和静态方法。这为接口提供了一种向后兼容的方式去扩展新功能,以及提供工具方法。
示例代码
Lambda表达式作为方法参数
java
@FunctionalInterface
interface MyFunction<T> {
T apply(T t);
}
public static void processString(String str, MyFunction<String> function) {
String result = function.apply(str);
System.out.println(result);
}
public static void main(String[] args) {
String input = "Hello, World!";
processString(input, String::toUpperCase); // 使用方法引用
}
Lambda表达式与集合操作
java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 过滤
List<String> filteredNames = names.stream()
.filter(name -> name.length() > 4)
.collect(Collectors.toList());
// 映射
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
// 排序
List<String> sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
// 聚合
int sumOfNameLengths = names.stream()
.mapToInt(String::length)
.sum();
方法引用示例
java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 使用Lambda表达式
numbers.forEach(n -> System.out.println(n));
// 使用方法引用
numbers.forEach(System.out::println);
Stream API
Stream API 介绍
Java 8引入的Stream API是一个强大的工具集,用于处理集合和其他数据源,如文件或I/O通道。它提供了一种声明式的方式来进行数据处理,支持懒惰求值、并行执行等特性。下面是对Stream API的重点介绍以及一些基本操作的代码示例:
创建 Stream
-
从集合创建:
javaList<String> list = Arrays.asList("apple", "banana", "orange"); Stream<String> stream = list.stream(); // 或者 list.parallelStream() 以启用并行执行
-
通过静态方法创建:
javaStream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
过滤数据
-
filter()
方法可以根据提供的谓词筛选出符合条件的元素:javaList<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList());
映射数据
-
map()
方法用于转换集合中的元素:javaList<String> words = Arrays.asList("Hello", "World"); List<Integer> wordLengths = words.stream() .map(s -> s.length()) .collect(Collectors.toList());
排序数据
-
sorted()
方法可以对集合中的元素进行排序:javaList<String> names = Arrays.asList("Alice", "Bob", "Charlie"); List<String> sortedNames = names.stream() .sorted() .collect(Collectors.toList());
聚合数据
-
reduce()
方法可以将集合中的所有元素归约为单一结果:javaList<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum); // 或者使用 (a, b) -> a + b;
匹配数据
-
anyMatch()
方法检查是否有任何元素符合给定的条件:javaList<String> words = Arrays.asList("apple", "banana", "orange"); boolean containsA = words.stream() .anyMatch(s -> s.contains("a"));
其他功能
- 去重 :使用
distinct()
去除重复元素。 - 分组 :使用
groupingBy()
按照某个属性对元素进行分组。 - 归约 :除了
reduce()
外,还可以使用collectingAndThen()
等方法进行复杂的归约操作。
这些操作可以组合在一起形成流水线,从而以一种声明式的方式处理数据。例如:
java
List<String> words = Arrays.asList("apple", "banana", "orange");
List<Integer> lengths = words.stream()
.filter(w -> w.contains("a"))
.map(String::length)
.collect(Collectors.toList());
以上就是关于Java 8 Stream API的基本介绍和一些常见操作的示例。Stream API不仅让集合操作变得简单,还提供了更好的可读性和更高的性能。
java.time包
新的日期和时间API(java.time包)
Java 8引入了新的日期和时间API,该API位于java.time
包下,提供了一系列类来更好地处理日期和时间。下面是该API的一些关键特性及代码示例:
LocalDate
-
用于表示日期,不包含时间和时区信息。
-
创建当前日期:
javaLocalDate currentDate = LocalDate.now(); System.out.println(currentDate); // 输出:2024-09-20(假设当前日期为2024年9月20日)
-
创建指定日期:
javaLocalDate specificDate = LocalDate.of(2024, Month.SEPTEMBER, 20); System.out.println(specificDate); // 输出:2024-09-20
LocalTime
-
用于表示时间,不包含日期和时区信息。
-
创建当前时间:
javaLocalTime currentTime = LocalTime.now(); System.out.println(currentTime); // 输出:19:05 (假设当前时间为19时05分)
-
创建指定时间:
javaLocalTime specificTime = LocalTime.of(19, 5); System.out.println(specificTime); // 输出:19:05
LocalDateTime
-
用于表示日期和时间,不包含时区信息。
-
创建当前日期和时间:
javaLocalDateTime currentDateTime = LocalDateTime.now(); System.out.println(currentDateTime); // 输出:2024-09-20T19:05
-
创建指定日期和时间:
javaLocalDateTime specificDateTime = LocalDateTime.of(2024, Month.SEPTEMBER, 20, 19, 5); System.out.println(specificDateTime); // 输出:2024-09-20T19:05
DateTimeFormatter
-
用于格式化和解析日期时间对象。
-
格式化日期时间为字符串:
javaLocalDateTime currentDateTime = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formattedDateTime = currentDateTime.format(formatter); System.out.println(formattedDateTime); // 输出:2024-09-20 19:05
-
解析字符串为日期时间:
javaString dateTimeString = "2024-09-20 19:05"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString, formatter); System.out.println(parsedDateTime); // 输出:2024-09-20T19:05
其他相关类
此外,java.time
包还提供了其他几个有用的类,如:
- ZonedDateTime:代表带有时区的日期时间。
- OffsetDateTime:代表带有偏移量的日期时间。
- Duration 和 Period:分别用于表示两个时间点之间的持续时间和日期间隔。
- Instant:代表时间戳,通常用于与时钟系统交互。
默认方法和静态方法
默认方法和静态方法
Java 8引入了两种新的方法类型,允许在接口中定义更多的行为而不破坏现有的实现。以下是关于这两种方法类型的详细介绍和示例代码。
默认方法
默认方法(default method)是在接口中定义的一种特殊类型的方法,它提供了一个默认的实现。这种机制允许在不改变现有实现类的前提下,向接口中添加新方法。默认方法使用default
关键字声明。
示例代码:
java
public interface MyInterface {
// 默认方法
default void myDefaultMethod() {
System.out.println("这是默认方法");
}
}
public class MyClass implements MyInterface {
// 不需要重新实现这个方法,除非你想覆盖默认的行为
}
public class Main {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.myDefaultMethod(); // 输出:这是默认方法
}
}
在这个例子中,MyInterface
接口包含了一个默认方法myDefaultMethod()
。由于MyClass
实现了MyInterface
,并且没有提供自己的实现,所以它将使用接口中定义的默认实现。
静态方法
静态方法(static method)是在接口中定义的公共静态方法,它们不是接口实现的一部分,而是属于接口本身的工具方法。这些方法可以直接通过接口名来调用,不需要实例化接口的实现类。
示例代码:
java
public interface MyInterface {
// 静态方法
static void myStaticMethod() {
System.out.println("这是静态方法");
}
}
public class Main {
public static void main(String[] args) {
MyInterface.myStaticMethod(); // 输出:这是静态方法
}
}
在这个例子中,MyInterface
接口包含了一个静态方法myStaticMethod()
。由于它是静态的,可以通过接口名直接调用来执行。
总结
- 默认方法:允许在不修改现有实现类的情况下向接口添加新的方法。这对于向旧的接口添加新的功能尤其有用,因为它可以为新方法提供一个默认实现,现有类可以选择是否覆盖这个默认行为。
- 静态方法:提供了一种在接口级别上定义工具方法的方式。这些方法独立于任何特定的接口实现,并且可以直接通过接口名来访问。
方法引用
方法引用是Java 8引入的一项特性,它允许我们引用已有的方法或构造器作为Lambda表达式的替代,从而使得代码更加简洁和易读。以下是关于方法引用的不同类型的详细说明及示例代码。
静态方法引用
静态方法引用允许你引用一个类中的静态方法。格式如下:
类名::静态方法名
示例代码:
java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.map(Integer::valueOf) // 引用静态方法:Integer.valueOf
.forEach(System.out::println); // 引用实例方法:System.out.println
实例方法引用
实例方法引用允许你引用一个特定对象的实例方法。格式如下:
实例对象::实例方法名
示例代码:
java
String str = "hello";
Function<String, Integer> func = str::length; // 引用实例方法:String.length
int length = func.apply(str);
类的任意对象方法引用
这类方法引用允许你引用一个类的任意实例的方法,而不是特定的实例。格式如下:
类名::实例方法名
示例代码:
java
List<String> strings = Arrays.asList("apple", "banana", "orange");
strings.stream()
.map(String::toUpperCase) // 引用实例方法:String.toUpperCase
.forEach(System.out::println); // 引用实例方法:System.out.println
构造方法引用
构造方法引用允许你引用一个类的构造方法来创建新的对象。格式如下:
类名::new
示例代码:
java
Supplier<List<String>> supplier = ArrayList::new; // 引用构造方法:ArrayList()
List<String> list = supplier.get();
注意事项
尽管方法引用非常有用,但在使用时也需要注意以下几点:
- 适用性:只有当Lambda表达式的功能与某个已存在的方法完全一致时,才可以使用方法引用。
- 目标类型:方法引用的目标类型应该是一个函数式接口,即一个只有一个抽象方法的接口。
- 参数匹配:引用的方法的参数列表必须与Lambda表达式的参数列表相匹配。
- 返回类型:引用的方法返回类型必须与Lambda表达式的返回类型相匹配。