- Java 8 Tutorial
- Java 8 - Home
- Java 8 - Overview
- Java 8 - Environment Setup
- Java 8 - Lambda Expressions
- Java 8 - Method References
- Java 8 - Functional Interfaces
- Java 8 - Default Methods
- Java 8 - Streams
- Java 8 - Optional Class
- Java 8 - Nashorn JavaScript
- Java 8 - New Date/Time API
- Java 8 - Base64
- Java 8 Useful Resources
- Java 8 - Questions and Answers
- Java 8 - Quick Guide
- Java 8 - Useful Resources
- Java 8 - Discussion
Java 8 - 快速指南
Java 8 - 概述
JAVA 8是JAVA编程语言开发的一个主要功能版本。它的初始版本于 2014 年 3 月 18 日发布。随着 Java 8 的发布,Java 提供了对函数式编程、新的 JavaScript 引擎、用于日期时间操作的新 API、新的流 API 等的支持。
新功能
Lambda 表达式- 为 Java 添加函数处理能力。
方法引用- 通过名称引用函数,而不是直接调用它们。使用函数作为参数。
默认方法- 具有默认方法实现的接口。
新工具- 添加了新的编译器工具和实用程序,例如“jdeps”以找出依赖关系。
Stream API - 新的流API以促进管道处理。
日期时间 API - 改进的日期时间 API。
可选- 强调正确处理空值的最佳实践。
Nashorn,JavaScript 引擎- 一个基于 Java 的引擎,用于执行 JavaScript 代码。
考虑以下代码片段。
现场演示import java.util.Collections; import java.util.List; import java.util.ArrayList; import java.util.Comparator; public class Java8Tester { public static void main(String args[]) { List<String> names1 = new ArrayList<String>(); names1.add("Mahesh "); names1.add("Suresh "); names1.add("Ramesh "); names1.add("Naresh "); names1.add("Kalpesh "); List<String> names2 = new ArrayList<String>(); names2.add("Mahesh "); names2.add("Suresh "); names2.add("Ramesh "); names2.add("Naresh "); names2.add("Kalpesh "); Java8Tester tester = new Java8Tester(); System.out.println("Sort using Java 7 syntax: "); tester.sortUsingJava7(names1); System.out.println(names1); System.out.println("Sort using Java 8 syntax: "); tester.sortUsingJava8(names2); System.out.println(names2); } //sort using java 7 private void sortUsingJava7(List<String> names) { Collections.sort(names, new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }); } //sort using java 8 private void sortUsingJava8(List<String> names) { Collections.sort(names, (s1, s2) -> s1.compareTo(s2)); } }
运行程序得到如下结果。
Sort using Java 7 syntax: [ Kalpesh Mahesh Naresh Ramesh Suresh ] Sort using Java 8 syntax: [ Kalpesh Mahesh Naresh Ramesh Suresh ]
这里的sortUsingJava8()方法使用排序函数并以 lambda 表达式作为参数来获取排序标准。
Java 8 - 环境设置
本地环境设置
如果您想设置自己的 Java 编程语言环境,那么本节将指导您完成整个过程。请按照以下步骤设置您的 Java 环境。
Java SE 可以从以下链接免费下载 -
https://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html
您可以根据您的操作系统下载一个版本。
按照说明下载 Java,然后运行.exe以在您的计算机上安装 Java。在计算机上安装 Java 后,您需要设置环境变量以指向正确的安装目录。
设置 Windows 2000/XP 的路径
假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -
右键单击“我的电脑”并选择“属性”。
单击“高级”选项卡下的“环境变量”按钮。
现在,更改“Path”变量,使其也包含 Java 可执行文件的路径。例如,如果路径当前设置为“C:\WINDOWS\SYSTEM32”,则将路径更改为“C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin”。
设置Windows 95/98/ME的路径
假设您已将 Java 安装在 c:\Program Files\java\jdk 目录中 -
编辑“C:\autoexec.bat”文件并在末尾添加以下行 -
设置路径=%PATH%;C:\Program Files\java\jdk\bin
设置 Linux、UNIX、Solaris、FreeBSD 的路径
应将环境变量 PATH 设置为指向 Java 二进制文件的安装位置。如果您在执行此操作时遇到问题,请参阅您的 shell 文档。
例如,如果您使用 bash 作为 shell,那么您可以在 '.bashrc:export PATH=/path/to/java:$PATH' 的末尾添加以下行
流行的 Java 编辑器
要编写 Java 程序,您需要一个文本编辑器。市场上还有更复杂的 IDE。但现在,您可以考虑以下其中一项 -
记事本- 在 Windows 计算机上,您可以使用任何简单的文本编辑器,例如记事本(本教程推荐)或 TextPad。
Netbeans - 它是一个开源且免费的 Java IDE。可以从https://netbeans.org/index.html下载。
Eclipse - 它也是由 Eclipse 开源社区开发的 Java IDE,可以从https://www.eclipse.org/下载。
Java 8 - Lambda 表达式
Java 8 中引入了 Lambda 表达式,被誉为 Java 8 最大的特性。Lambda 表达式方便了函数式编程,大大简化了开发。
句法
lambda 表达式具有以下语法特征。
parameter -> expression body
以下是 lambda 表达式的重要特征。
可选类型声明- 无需声明参数的类型。编译器可以从参数的值推断出相同的结果。
参数周围的可选括号- 无需在括号中声明单个参数。对于多个参数,需要括号。
可选大括号- 如果表达式主体包含单个语句,则无需在表达式主体中使用大括号。
可选 return 关键字- 如果主体具有单个表达式来返回值,则编译器会自动返回值。需要大括号来指示表达式返回值。
Lambda 表达式示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示public class Java8Tester { public static void main(String args[]) { Java8Tester tester = new Java8Tester(); //with type declaration MathOperation addition = (int a, int b) -> a + b; //with out type declaration MathOperation subtraction = (a, b) -> a - b; //with return statement along with curly braces MathOperation multiplication = (int a, int b) -> { return a * b; }; //without return statement and without curly braces MathOperation division = (int a, int b) -> a / b; System.out.println("10 + 5 = " + tester.operate(10, 5, addition)); System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction)); System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication)); System.out.println("10 / 5 = " + tester.operate(10, 5, division)); //without parenthesis GreetingService greetService1 = message -> System.out.println("Hello " + message); //with parenthesis GreetingService greetService2 = (message) -> System.out.println("Hello " + message); greetService1.sayMessage("Mahesh"); greetService2.sayMessage("Suresh"); } interface MathOperation { int operation(int a, int b); } interface GreetingService { void sayMessage(String message); } private int operate(int a, int b, MathOperation mathOperation) { return mathOperation.operation(a, b); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 Hello Mahesh Hello Suresh
以下是上述示例中需要考虑的要点。
Lambda 表达式主要用于定义函数接口的内联实现,即仅具有单个方法的接口。在上面的例子中,我们使用了各种类型的lambda表达式来定义MathOperation接口的运算方法。然后我们定义了GreetingService的sayMessage的实现。
Lambda 表达式消除了对匿名类的需要,并为 Java 提供了非常简单但强大的函数式编程能力。
范围
使用 lambda 表达式,您可以引用任何最终变量或有效最终变量(仅分配一次)。如果第二次为变量赋值,则 Lambda 表达式会引发编译错误。
范围示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示public class Java8Tester { final static String salutation = "Hello! "; public static void main(String args[]) { GreetingService greetService1 = message -> System.out.println(salutation + message); greetService1.sayMessage("Mahesh"); } interface GreetingService { void sayMessage(String message); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Hello! Mahesh
Java 8 - 方法参考
方法引用有助于通过名称指向方法。使用“::”符号描述方法引用。方法引用可用于指向以下类型的方法 -
- 静态方法
- 实例方法
- 使用 new 运算符的构造函数 (TreeSet::new)
方法参考示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
import java.util.List; import java.util.ArrayList; public class Java8Tester { public static void main(String args[]) { List names = new ArrayList(); names.add("Mahesh"); names.add("Suresh"); names.add("Ramesh"); names.add("Naresh"); names.add("Kalpesh"); names.forEach(System.out::println); } }
这里我们将 System.out::println 方法作为静态方法引用传递。
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Mahesh Suresh Ramesh Naresh Kalpesh
Java 8 - 函数式接口
函数式接口具有单一的功能来展示。例如,具有单个方法“compareTo”的 Comparable 接口用于比较目的。Java 8 定义了许多函数式接口,广泛用于 lambda 表达式。以下是 java.util.Function 包中定义的函数接口列表。
先生。 | 接口及说明 |
---|---|
1 | BiConsumer<T,U> 表示接受两个输入参数且不返回结果的操作。 |
2 | 双函数<T,U,R> 表示接受两个参数并产生结果的函数。 |
3 | 二元运算符<T> 表示对两个相同类型的操作数进行运算,产生与操作数相同类型的结果。 |
4 | 双谓词<T,U> 表示两个参数的谓词(布尔值函数)。 |
5 | 布尔供应商 代表布尔值结果的提供者。 |
6 | 消费者<T> 表示接受单个输入参数且不返回结果的操作。 |
7 | 双二元运算符 表示对两个双值操作数进行运算并生成双值结果。 |
8 | 双重消费者 表示接受单个双值参数且不返回结果的操作。 |
9 | 双功能<R> 表示接受双值参数并生成结果的函数。 |
10 | 双谓词 表示一个双值参数的谓词(布尔值函数)。 |
11 | 双供应商 代表双值结果的提供者。 |
12 | DoubleToInt 函数 表示接受双值参数并生成 int 值结果的函数。 |
13 | DoubleToLong 函数 表示接受双值参数并生成长值结果的函数。 |
14 | 双一元运算符 表示对单个双值操作数产生双值结果的运算。 |
15 | 函数<T,R> 表示一个函数,它接受一个参数并产生一个结果。 |
16 | 整数二元运算符 表示对两个 int 值操作数的运算并产生 int 值结果。 |
17 号 | 国际消费者 表示接受单个 int 值参数且不返回结果的操作。 |
18 | 整数函数<R> 表示接受 int 值参数并生成结果的函数。 |
19 | 内部谓词 表示一个 int 值参数的谓词(布尔值函数)。 |
20 | 国际供应商 代表 int 值结果的提供者。 |
21 | 整数转双精度函数 表示接受 int 值参数并生成双值结果的函数。 |
22 | IntToLong函数 表示接受 int 值参数并生成 long 值结果的函数。 |
23 | 整型一元运算符 表示对单个 int 值操作数进行的操作,该操作会生成 int 值结果。 |
24 | 长二元运算符 表示对两个长值操作数的运算并产生长值结果。 |
25 | 长消费者 表示接受单个长值参数且不返回结果的操作。 |
26 | 长函数<R> 表示接受长值参数并生成结果的函数。 |
27 | 长谓词 表示一个长值参数的谓词(布尔值函数)。 |
28 | 长供应商 代表长期有价值的结果的提供者。 |
29 | 长到双功能 表示接受长值参数并生成双值结果的函数。 |
30 | LongToInt函数 表示接受长值参数并生成 int 值结果的函数。 |
31 | 长一元运算符 表示对单个长值操作数进行的操作,该操作会生成长值结果。 |
32 | ObjDoubleConsumer<T> 表示接受对象值和双值参数的操作,并且不返回结果。 |
33 | ObjIntConsumer<T> 表示接受对象值和 int 值参数且不返回结果的操作。 |
34 | ObjLongConsumer<T> 表示接受对象值和长值参数的操作,并且不返回结果。 |
35 | 谓词<T> 表示一个参数的谓词(布尔值函数)。 |
36 | 供应商<T> 代表结果的提供者。 |
37 | ToDoubleBiFunction<T,U> 表示接受两个参数并生成双值结果的函数。 |
38 | ToDoubleFunction<T> 表示产生双值结果的函数。 |
39 | ToIntBiFunction<T,U> 表示接受两个参数并生成 int 值结果的函数。 |
40 | ToIntFunction<T> 表示产生 int 值结果的函数。 |
41 | ToLongBi函数<T,U> 表示接受两个参数并生成长值结果的函数。 |
42 | ToLong函数<T> 表示产生长值结果的函数。 |
43 | 一元运算符<T> 表示对单个操作数的操作,产生与其操作数相同类型的结果。 |
函数式接口示例
Predicate <T> 接口是一个函数式接口,其方法 test(Object) 返回布尔值。这个接口表示一个对象被测试为真或假。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class Java8Tester { public static void main(String args[]) { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // Predicate<Integer> predicate = n -> true // n is passed as parameter to test method of Predicate interface // test method will always return true no matter what value n has. System.out.println("Print all numbers:"); //pass n as parameter eval(list, n->true); // Predicate<Integer> predicate1 = n -> n%2 == 0 // n is passed as parameter to test method of Predicate interface // test method will return true if n%2 comes to be zero System.out.println("Print even numbers:"); eval(list, n-> n%2 == 0 ); // Predicate<Integer> predicate2 = n -> n > 3 // n is passed as parameter to test method of Predicate interface // test method will return true if n is greater than 3. System.out.println("Print numbers greater than 3:"); eval(list, n-> n > 3 ); } public static void eval(List<Integer> list, Predicate<Integer> predicate) { for(Integer n: list) { if(predicate.test(n)) { System.out.println(n + " "); } } } }
这里我们传递了 Predicate 接口,它接受单个输入并返回布尔值。
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Print all numbers: 1 2 3 4 5 6 7 8 9 Print even numbers: 2 4 6 8 Print numbers greater than 3: 4 5 6 7 8 9
Java 8 - 默认方法
Java 8 引入了接口中默认方法实现的新概念。添加此功能是为了向后兼容,以便可以使用旧接口来利用 Java 8 的 lambda 表达式功能。
例如,“List”或“Collection”接口没有“forEach”方法声明。因此,添加这样的方法只会破坏集合框架的实现。Java 8引入了默认方法,使得List/Collection接口可以有forEach方法的默认实现,而实现这些接口的类不需要实现相同的方法。
句法
public interface vehicle { default void print() { System.out.println("I am a vehicle!"); } }
多重默认
对于接口中的默认函数,一个类可能会实现两个具有相同默认方法的接口。以下代码解释了如何解决这种歧义。
public interface vehicle { default void print() { System.out.println("I am a vehicle!"); } } public interface fourWheeler { default void print() { System.out.println("I am a four wheeler!"); } }
第一个解决方案是创建一个自己的方法来覆盖默认实现。
public class car implements vehicle, fourWheeler { public void print() { System.out.println("I am a four wheeler car vehicle!"); } }
第二种解决方案是使用 super 调用指定接口的默认方法。
public class car implements vehicle, fourWheeler { public void print() { vehicle.super.print(); } }
静态默认方法
从 Java 8 开始,接口还可以具有静态帮助器方法。
public interface vehicle { default void print() { System.out.println("I am a vehicle!"); } static void blowHorn() { System.out.println("Blowing horn!!!"); } }
默认方法示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示public class Java8Tester { public static void main(String args[]) { Vehicle vehicle = new Car(); vehicle.print(); } } interface Vehicle { default void print() { System.out.println("I am a vehicle!"); } static void blowHorn() { System.out.println("Blowing horn!!!"); } } interface FourWheeler { default void print() { System.out.println("I am a four wheeler!"); } } class Car implements Vehicle, FourWheeler { public void print() { Vehicle.super.print(); FourWheeler.super.print(); Vehicle.blowHorn(); System.out.println("I am a car!"); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
I am a vehicle! I am a four wheeler! Blowing horn!!! I am a car!
Java 8 - 流
Stream是Java 8中引入的一个新的抽象层。使用stream,您可以以类似于SQL语句的声明式方式处理数据。例如,考虑以下 SQL 语句。
SELECT max(salary), employee_id, employee_name FROM Employee
上面的 SQL 表达式自动返回最高薪员工的详细信息,而无需在开发人员端进行任何计算。使用Java中的集合框架,开发人员必须使用循环并进行重复检查。另一个问题是效率;由于多核处理器可以轻松使用,Java 开发人员必须编写非常容易出错的并行代码处理。
为了解决此类问题,Java 8 引入了流的概念,使开发人员能够以声明方式处理数据并利用多核架构,而无需为其编写任何特定代码。
什么是流?
Stream 表示来自源的对象序列,支持聚合操作。以下是流的特征 -
元素序列- 流以顺序方式提供一组特定类型的元素。流按需获取/计算元素。它从不存储元素。
Source - Stream 将集合、数组或 I/O 资源作为输入源。
聚合操作- Stream 支持聚合操作,如过滤器、映射、限制、减少、查找、匹配等。
管道化- 大多数流操作返回流本身,以便可以管道化它们的结果。这些操作称为中间操作,它们的功能是获取输入、处理输入并将输出返回到目标。collect() 方法是一个终端操作,通常出现在流水线操作的末尾,以标记流的结束。
自动迭代- 流操作在提供的源元素上进行内部迭代,这与需要显式迭代的集合相反。
生成流
在 Java 8 中,Collection 接口有两种方法来生成 Stream。
Stream() - 返回一个将集合作为其源的顺序流。
parallelStream() - 返回一个并行流,考虑集合作为其源。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
对于每个
Stream 提供了一个新方法“forEach”来迭代流的每个元素。以下代码段显示如何使用 forEach 打印 10 个随机数。
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
地图
'map' 方法用于将每个元素映射到其相应的结果。以下代码段使用 map 打印唯一的数字方块。
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
筛选
“过滤”方法用于根据标准消除元素。以下代码段使用过滤器打印空字符串的计数。
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count();
限制
“limit”方法用于减小流的大小。以下代码段显示如何使用 limit 打印 10 个随机数。
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
已排序
'sorted' 方法用于对流进行排序。以下代码段显示如何按排序顺序打印 10 个随机数。
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
并行处理
parallelStream 是用于并行处理的流的替代方案。看一下下面的代码段,它使用并行流打印空字符串的计数。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
在顺序流和并行流之间切换非常容易。
收藏家
收集器用于组合流元素的处理结果。收集器可用于返回列表或字符串。
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString);
统计数据
在 Java 8 中,引入了统计收集器来在流处理完成时计算所有统计信息。
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Highest number in List : " + stats.getMax()); System.out.println("Lowest number in List : " + stats.getMin()); System.out.println("Sum of all numbers : " + stats.getSum()); System.out.println("Average of all numbers : " + stats.getAverage());
流示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.util.ArrayList; import java.util.Arrays; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.Map; public class Java8Tester { public static void main(String args[]) { System.out.println("Using Java 7: "); // Count empty strings List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("List: " +strings); long count = getCountEmptyStringUsingJava7(strings); System.out.println("Empty Strings: " + count); count = getCountLength3UsingJava7(strings); System.out.println("Strings of length 3: " + count); //Eliminate empty string List<String> filtered = deleteEmptyStringsUsingJava7(strings); System.out.println("Filtered List: " + filtered); //Eliminate empty string and join using comma. String mergedString = getMergedStringUsingJava7(strings,", "); System.out.println("Merged String: " + mergedString); List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of square of distinct numbers List<Integer> squaresList = getSquares(numbers); System.out.println("Squares List: " + squaresList); List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19); System.out.println("List: " +integers); System.out.println("Highest number in List : " + getMax(integers)); System.out.println("Lowest number in List : " + getMin(integers)); System.out.println("Sum of all numbers : " + getSum(integers)); System.out.println("Average of all numbers : " + getAverage(integers)); System.out.println("Random Numbers: "); //print ten random numbers Random random = new Random(); for(int i = 0; i < 10; i++) { System.out.println(random.nextInt()); } System.out.println("Using Java 8: "); System.out.println("List: " +strings); count = strings.stream().filter(string->string.isEmpty()).count(); System.out.println("Empty Strings: " + count); count = strings.stream().filter(string -> string.length() == 3).count(); System.out.println("Strings of length 3: " + count); filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList()); System.out.println("Squares List: " + squaresList); System.out.println("List: " +integers); IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics(); System.out.println("Highest number in List : " + stats.getMax()); System.out.println("Lowest number in List : " + stats.getMin()); System.out.println("Sum of all numbers : " + stats.getSum()); System.out.println("Average of all numbers : " + stats.getAverage()); System.out.println("Random Numbers: "); random.ints().limit(10).sorted().forEach(System.out::println); //parallel processing count = strings.parallelStream().filter(string -> string.isEmpty()).count(); System.out.println("Empty Strings: " + count); } private static int getCountEmptyStringUsingJava7(List<String> strings) { int count = 0; for(String string: strings) { if(string.isEmpty()) { count++; } } return count; } private static int getCountLength3UsingJava7(List<String> strings) { int count = 0; for(String string: strings) { if(string.length() == 3) { count++; } } return count; } private static List<String> deleteEmptyStringsUsingJava7(List<String> strings) { List<String> filteredList = new ArrayList<String>(); for(String string: strings) { if(!string.isEmpty()) { filteredList.add(string); } } return filteredList; } private static String getMergedStringUsingJava7(List<String> strings, String separator) { StringBuilder stringBuilder = new StringBuilder(); for(String string: strings) { if(!string.isEmpty()) { stringBuilder.append(string); stringBuilder.append(separator); } } String mergedString = stringBuilder.toString(); return mergedString.substring(0, mergedString.length()-2); } private static List<Integer> getSquares(List<Integer> numbers) { List<Integer> squaresList = new ArrayList<Integer>(); for(Integer number: numbers) { Integer square = new Integer(number.intValue() * number.intValue()); if(!squaresList.contains(square)) { squaresList.add(square); } } return squaresList; } private static int getMax(List<Integer> numbers) { int max = numbers.get(0); for(int i = 1;i < numbers.size();i++) { Integer number = numbers.get(i); if(number.intValue() > max) { max = number.intValue(); } } return max; } private static int getMin(List<Integer> numbers) { int min = numbers.get(0); for(int i= 1;i < numbers.size();i++) { Integer number = numbers.get(i); if(number.intValue() < min) { min = number.intValue(); } } return min; } private static int getSum(List numbers) { int sum = (int)(numbers.get(0)); for(int i = 1;i < numbers.size();i++) { sum += (int)numbers.get(i); } return sum; } private static int getAverage(List<Integer> numbers) { return getSum(numbers) / numbers.size(); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下结果 -
Using Java 7: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9 Random Numbers: -1279735475 903418352 -1133928044 -1571118911 628530462 18407523 -881538250 -718932165 270259229 421676854 Using Java 8: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9.444444444444445 Random Numbers: -1009474951 -551240647 -2484714 181614550 933444268 1227850416 1579250773 1627454872 1683033687 1798939493 Empty Strings: 2
Java 8 - 可选类
Optional 是一个容器对象,用于包含非空对象。可选对象用于表示缺少值的 null。此类具有各种实用方法,可帮助代码将值处理为“可用”或“不可用”,而不是检查空值。它是在Java 8中引入的,类似于Guava中的Optional。
类别声明
以下是java.util.Optional<T>类的声明-
public final class Optional<T> extends Object
类方法
先生。 | 方法及说明 |
---|---|
1 | 静态 <T> 可选 <T> 空() 返回一个空的可选实例。 |
2 | 布尔等于(对象 obj) 指示某个其他对象是否“等于”此可选对象。 |
3 | 可选<T>过滤器(谓词<?超级<T>谓词) 如果存在值并且该值与给定谓词匹配,则返回描述该值的可选值,否则返回空可选值。 |
4 | <U> 可选<U> flatMap(Function<? super T,可选<U>> 映射器) 如果存在值,则会将提供的可选承载映射函数应用于该值,返回该结果,否则返回空的可选值。 |
5 | 获取() 如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException。 |
6 | int 哈希码() 返回当前值的哈希码值(如果有);如果不存在值,则返回 0(零)。 |
7 | void ifPresent(Consumer<? super T> 消费者) 如果存在值,它将使用该值调用指定的使用者,否则不执行任何操作。 |
8 | 布尔值 isPresent() 如果存在值则返回 true,否则返回 false。 |
9 | <U>可选<U>映射(函数<?super T,?extends U>映射器) 如果存在值,则对其应用提供的映射函数,如果结果非空,则返回描述结果的可选值。 |
10 | static <T> 可选<T> of(T 值) 返回具有指定的当前非空值的可选值。 |
11 | static <T> 可选<T> ofNullable(T 值) 如果非空,则返回描述指定值的可选值,否则返回空可选值。 |
12 | T orElse(T 其他) 如果存在则返回值,否则返回其他值。 |
13 | T orElseGet(Supplier<? extends T> other) 如果存在则返回该值,否则调用 other 并返回该调用的结果。 |
14 | <X 扩展 Throwable> T 或 ElseThrow(Supplier<? 扩展 X> 异常供应商) 返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。 |
15 | 字符串转字符串() 返回此可选值的非空字符串表示形式,适合调试。 |
该类继承了以下类的方法 -
- java.lang.Object
可选示例
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.util.Optional; public class Java8Tester { public static void main(String args[]) { Java8Tester java8Tester = new Java8Tester(); Integer value1 = null; Integer value2 = new Integer(10); //Optional.ofNullable - allows passed parameter to be null. Optional<Integer> a = Optional.ofNullable(value1); //Optional.of - throws NullPointerException if passed parameter is null Optional<Integer> b = Optional.of(value2); System.out.println(java8Tester.sum(a,b)); } public Integer sum(Optional<Integer> a, Optional<Integer> b) { //Optional.isPresent - checks the value is present or not System.out.println("First parameter is present: " + a.isPresent()); System.out.println("Second parameter is present: " + b.isPresent()); //Optional.orElse - returns the value if present otherwise returns //the default value passed. Integer value1 = a.orElse(new Integer(0)); //Optional.get - gets the value, value should be present Integer value2 = b.get(); return value1 + value2; } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
First parameter is present: false Second parameter is present: true 10
Java 8 - Nashorn JavaScript
Java 8 Nashorn 引入了一个经过大幅改进的 JavaScript 引擎,以取代现有的 Rhino。Nashorn 的性能提高了 2 到 10 倍,因为它直接在内存中编译代码并将字节码传递给 JVM。Nashorn 使用 Java 7 中引入的动态调用功能来提高性能。
杰杰斯
对于 Nashorn 引擎,JAVA 8 引入了一个新的命令行工具jjs,用于在控制台执行 javascript 代码。
解释js文件
创建文件example.js并将其保存在 c:\> JAVA 文件夹中。
示例.js
print('Hello World!');
打开控制台并使用以下命令。
C:\JAVA>jjs sample.js
它将产生以下输出:
Hello World!
jjs 交互模式
打开控制台并使用以下命令。
C:\JAVA>jjs jjs> print("Hello, World!") Hello, World! jjs> quit() >>
传递参数
打开控制台并使用以下命令。
C:\JAVA> jjs -- a b c jjs> print('letters: ' +arguments.join(", ")) letters: a, b, c jjs>
从 Java 调用 JavaScript
使用ScriptEngineManager,可以用Java调用和解释JavaScript代码。
例子
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import javax.script.ScriptException; public class Java8Tester { public static void main(String args[]) { ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn"); String name = "Mahesh"; Integer result = null; try { nashorn.eval("print('" + name + "')"); result = (Integer) nashorn.eval("10 + 2"); } catch(ScriptException e) { System.out.println("Error executing script: "+ e.getMessage()); } System.out.println(result.toString()); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下结果 -
Mahesh 12
从 JavaScript 调用 Java
以下示例说明了如何在 java 脚本中导入和使用 Java 类。
创建Sample.js并将其保存在 c:\> JAVA 文件夹中。
示例.js
var BigDecimal = Java.type('java.math.BigDecimal'); function calculate(amount, percentage) { var result = new BigDecimal(amount).multiply(new BigDecimal(percentage)).divide( new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_EVEN); return result.toPlainString(); } var result = calculate(568000000000000000023,13.9); print(result);
打开控制台并使用以下命令。
C:\JAVA>jjs sample.js
它应该产生以下输出 -
78952000000000000003.20
Java 8 - 新的日期/时间 API
Java 8 引入了新的日期时间 API,以弥补旧日期时间 API 的以下缺点。
不是线程安全的- java.util.Date 不是线程安全的,因此开发人员在使用日期时必须处理并发问题。新的日期时间 API 是不可变的,并且没有 setter 方法。
糟糕的设计- 默认日期从 1900 年开始,月份从 1 开始,日期从 0 开始,所以没有统一性。旧的 API 对于日期操作的直接方法较少。新的 API 为此类操作提供了许多实用方法。
困难的时区处理- 开发人员必须编写大量代码来处理时区问题。新 API 的开发始终考虑到特定领域的设计。
Java 8 在 java.time 包下引入了一个新的日期时间 API。以下是java.time包中引入的一些重要类。
Local - 简化的日期时间 API,没有时区处理的复杂性。
Zoned - 专门的日期时间 API 来处理各种时区。
本地日期时间 API
LocalDate/LocalTime 和 LocalDateTime 类简化了不需要时区的开发。让我们看看他们的实际行动。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 java 程序。
Java8Tester.java
现场演示import java.time.LocalDate; import java.time.LocalTime; import java.time.LocalDateTime; import java.time.Month; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testLocalDateTime(); } public void testLocalDateTime() { // Get the current date and time LocalDateTime currentTime = LocalDateTime.now(); System.out.println("Current DateTime: " + currentTime); LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); Month month = currentTime.getMonth(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("Month: " + month +"day: " + day +"seconds: " + seconds); LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012); System.out.println("date2: " + date2); //12 december 2014 LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12); System.out.println("date3: " + date3); //22 hour 15 minutes LocalTime date4 = LocalTime.of(22, 15); System.out.println("date4: " + date4); //parse a string LocalTime date5 = LocalTime.parse("20:15:30"); System.out.println("date5: " + date5); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Current DateTime: 2014-12-09T11:00:45.457 date1: 2014-12-09 Month: DECEMBERday: 9seconds: 45 date2: 2012-12-10T11:00:45.457 date3: 2014-12-12 date4: 22:15 date5: 20:15:30
分区日期时间 API
当考虑时区时,将使用分区日期时间 API。让我们看看他们的实际行动。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.time.ZonedDateTime; import java.time.ZoneId; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testZonedDateTime(); } public void testZonedDateTime() { // Get the current date and time ZonedDateTime date1 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]"); System.out.println("date1: " + date1); ZoneId id = ZoneId.of("Europe/Paris"); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("CurrentZone: " + currentZone); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
date1: 2007-12-03T10:15:30+05:00[Asia/Karachi] ZoneId: Europe/Paris CurrentZone: Etc/UTC
计时单位枚举
Java 8 中添加了 java.time.temporal.ChronoUnit 枚举,以替换旧 API 中用于表示日、月等的整数值。让我们看看它们的实际效果。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.time.LocalDate; import java.time.temporal.ChronoUnit; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testChromoUnits(); } public void testChromoUnits() { //Get the current date LocalDate today = LocalDate.now(); System.out.println("Current date: " + today); //add 1 week to the current date LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); System.out.println("Next week: " + nextWeek); //add 1 month to the current date LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS); System.out.println("Next month: " + nextMonth); //add 1 year to the current date LocalDate nextYear = today.plus(1, ChronoUnit.YEARS); System.out.println("Next year: " + nextYear); //add 10 years to the current date LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES); System.out.println("Date after ten year: " + nextDecade); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下结果 -
Current date: 2014-12-10 Next week: 2014-12-17 Next month: 2015-01-10 Next year: 2015-12-10 Date after ten year: 2024-12-10
期间和持续时间
Java 8 引入了两个专门的类来处理时间差异。
周期- 它处理基于日期的时间量。
持续时间- 它处理基于时间的时间量。
让我们看看他们的实际行动。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.time.temporal.ChronoUnit; import java.time.LocalDate; import java.time.LocalTime; import java.time.Duration; import java.time.Period; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testPeriod(); java8tester.testDuration(); } public void testPeriod() { //Get the current date LocalDate date1 = LocalDate.now(); System.out.println("Current date: " + date1); //add 1 month to the current date LocalDate date2 = date1.plus(1, ChronoUnit.MONTHS); System.out.println("Next month: " + date2); Period period = Period.between(date2, date1); System.out.println("Period: " + period); } public void testDuration() { LocalTime time1 = LocalTime.now(); Duration twoHours = Duration.ofHours(2); LocalTime time2 = time1.plus(twoHours); Duration duration = Duration.between(time1, time2); System.out.println("Duration: " + duration); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Current date: 2014-12-10 Next month: 2015-01-10 Period: P-1M Duration: PT2H
时间调节器
TemporalAdjuster 用于执行日期数学运算。例如,获取“该月的第二个星期六”或“下星期二”。让我们看看他们的实际行动。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; import java.time.DayOfWeek; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testAdjusters(); } public void testAdjusters() { //Get the current date LocalDate date1 = LocalDate.now(); System.out.println("Current date: " + date1); //get the next tuesday LocalDate nextTuesday = date1.with(TemporalAdjusters.next(DayOfWeek.TUESDAY)); System.out.println("Next Tuesday on : " + nextTuesday); //get the second saturday of next month LocalDate firstInYear = LocalDate.of(date1.getYear(),date1.getMonth(), 1); LocalDate secondSaturday = firstInYear.with(TemporalAdjusters.nextOrSame( DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY)); System.out.println("Second Saturday on : " + secondSaturday); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下结果 -
Current date: 2014-12-10 Next Tuesday on : 2014-12-16 Second Saturday on : 2014-12-13
向后兼容性
原始 Date 和 Calendar 对象中添加了 toInstant() 方法,可用于将它们转换为新的 Date-Time API。使用 ofInstant(Insant,ZoneId) 方法获取 LocalDateTime 或 ZonedDateTime 对象。让我们看看他们的实际行动。
使用您选择的任何编辑器(例如 C:\> JAVA)创建以下 Java 程序。
Java8Tester.java
现场演示import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.util.Date; import java.time.Instant; import java.time.ZoneId; public class Java8Tester { public static void main(String args[]) { Java8Tester java8tester = new Java8Tester(); java8tester.testBackwardCompatability(); } public void testBackwardCompatability() { //Get the current date Date currentDate = new Date(); System.out.println("Current date: " + currentDate); //Get the instant of current date in terms of milliseconds Instant now = currentDate.toInstant(); ZoneId currentZone = ZoneId.systemDefault(); LocalDateTime localDateTime = LocalDateTime.ofInstant(now, currentZone); System.out.println("Local date: " + localDateTime); ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, currentZone); System.out.println("Zoned date: " + zonedDateTime); } }
验证结果
使用javac编译器编译该类,如下所示 -
C:\JAVA>javac Java8Tester.java
现在运行 Java8Tester,如下所示 -
C:\JAVA>java Java8Tester
它应该产生以下输出 -
Current date: Wed Dec 10 05:44:06 UTC 2014 Local date: 2014-12-10T05:44:06.635 Zoned date: 2014-12-10T05:44:06.635Z[Etc/UTC]
Java 8 - Base64
在 Java 8 中,Base64 终于得到了应有的回报。Java 8 现在具有用于 Base64 编码的内置编码器和解码器。在Java 8中,我们可以使用三种类型的Base64编码。
简单- 输出映射到 A-Za-z0-9+/ 中的一组字符。编码器不会在输出中添加任何换行,解码器会拒绝除 A-Za-z0-9+/ 之外的任何字符。
URL - 输出映射到 A-Za-z0-9+_ 中的字符集。输出是 URL 和文件名安全的。
MIME - 输出映射为 MIME 友好格式。输出以每行不超过 76 个字符的形式表示,并使用回车符 '\r' 后跟换行符 '\n' 作为行分隔符。编码输出末尾不存在行分隔符。