本文主要是对JAVA8新特性的理解文章,如果有什么需要改进的地方还请大佬指出
作者简介:大家好,我是青衿
博客首页:CSDN主页石马农青衿
每日一句:努力一点,优秀一点
Java8之前的接口中只能定义全局常量,抽象方法
Java8之后的接口中能定义全局常量,抽象方法,默认方法以及静态方法
请看下面示例代码:
public interface Vehicle {
//默认方法
default void print(){
System.out.println("我是一辆车!");
}
// 静态方法
static void blowHorn(){
System.out.println("按喇叭!!!");
}
}
Lambda 表达式本质上是一段匿名内部类,也可以是一段可以传递的代码
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread is running before Java8!");
}
}).start();
这是通过内部类的方式来重写run方法,使用Lambda表达式,还可以更加简洁:
new Thread( () -> System.out.println("Thread is running since Java8!") ).start();
函数接口指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。
Java 8 提供了一个特殊的注解@FunctionalInterface,举个简单的函数式接口的定义
@FunctionalInterface
public interface GreetingService {
void sayMessage(String message);
}
Java7 只能通过匿名内部类进行编程,例如:
GreetingService greetService = new GreetingService() {
@Override
public void sayMessage(String message) {
System.out.println("Hello " + message);
}
};
greetService.sayMessage("world");
Java8 可以采用 Lambda 表达方进行编程:
GreetingService greetService = message -> System.out.println("Hello " + message);
greetService.sayMessage("world");
Stream 流简单来说,我们可以使用 java.util.Stream 对一个包含一个或多个元素的集合做各种操作。这些操作可能是 中间操作 亦或是 终端操作。 终端操作会返回一个结果,而中间操作会返回一个 Stream 流。
1- 创建 Stream
一个数据源(如:集合、数组),获取一个流
2- 中间操作
一个中间操作链,对数据源的数据进行处理
3- 终止操作(终端操作)
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
filter方法用于通过设置的条件过滤出元素。
首先,我们创建一个 List 集合:
public class FilterStreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("周杰伦");
list.add("王力宏");
list.add("陶喆");
list.add("林俊杰");
Stream<String> stream = list.stream().filter(element -> element.contains("王"));
stream.forEach(System.out::println);
}
}
element -> element.contains(“王”) 就是筛选出带有“王”的字符串。
forEach() 方法接收的是一个 Consumer(Java 8 新增的一个函数式接口,接受一个输入参数并且无返回的操作)类型的参数,类名 :: 方法名是 Java 8 引入的新语法,System.out 返回 PrintStream 类,println 方法你应该知道是打印的。forEach方法用于迭代流中的每个数据,类似于下面的代码
for (String s : strs) {
System.out.println(s);
}
**注:**foreach 是一个终端操作,它的返参是 void, 我们无法对其再次进行流操作。
Sorted 同样是一个中间操作,它的返参是一个 Stream 流。另外,我们可以传入一个 Comparator 用来自定义排序,如果不传,则使用默认的排序规则。
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(5, 2, 1, 4, 3);
// 使用stream的sorted方法进行排序
List<Integer> sortedNumbers = numbers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers);
}
}
当你运行这段代码时,它会输出排序后的整数列表:
[1, 2, 3, 4, 5]
如果想通过某种操作把一个流中的元素转化成新的流中的元素,可以使用 map() 方法。
中间操作 Map 能够帮助我们将 List 中的每一个元素做功能处理。例如下面的示例,将英文字符串数组的元素全部改为大写。整数数组每个元素+3
public class StreamTest {
public static void main(String[] args) {
String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());
List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());
System.out.println("每个元素大写:" + strList);
System.out.println("每个元素+3:" + intListNew);
}
}
把 Stream 的流转成一个 Stream 的流。
程序输出的结果如下所示:
3
3
2
3
Collectors类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors可用于返回列表或字符串:
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 使用stream的map方法将每个整数转换为其字符串表示,然后收集到一个集合中
Set<String> numberSet = numbers.stream()
.map(String::valueOf)
.collect(Collectors.toSet());
System.out.println(numberSet);
}
}
当你运行这段代码时,它会输出收集后的集合:
[1, 2, 3, 4, 5]
注意,因为我们使用了map方法将每个整数转换为其字符串表示,所以集合中的元素是字符串,而不是整数。这就是Java Stream的map和Collectors.toSet方法的组合使用,它可以用来将Stream中的元素转换并收集到一个Set中。
count 是一个终端操作,它能够统计 stream 流中的元素总数,返回值是 long 类型。
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> words = Arrays.asList("Hello", "World", "I", "am", "AI");
// 使用stream的count方法计算元素数量
long count = words.stream()
.count();
System.out.println(count);
}
}
它可以用来计算Stream中的元素数量。
Optional是用于防范NullPointerException。
可以将 Optional 看做是包装对象(可能是 null, 也有可能非 null)的容器。当我们定义了 一个方法,这个方法返回的对象可能是空,也有可能非空的时候,我们就可以考虑用 Optional 来包装它,这也是在 Java 8 被推荐使用的做法。
public class OptionalTester {
public static void main(String[] args) {
OptionalTester tester = new OptionalTester();
Integer value1 = null;
Integer value2 = new Integer(10);
// Optional.ofNullable - 允许传递为 null 参数
Optional<Integer> a = Optional.ofNullable(value1);
// Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
Optional<Integer> b = Optional.of(value2);
System.out.println(tester.sum(a,b));
}
public Integer sum(Optional<Integer> a, Optional<Integer> b){
// Optional.isPresent - 判断值是否存在
System.out.println("第一个参数值存在: " + a.isPresent());
System.out.println("第二个参数值存在: " + b.isPresent());
// Optional.orElse - 如果值存在,返回它,否则返回默认值
Integer value1 = a.orElse(new Integer(0));
//Optional.get - 获取值,值需要存在
Integer value2 = b.get();
return value1 + value2;
}
}