JAVA 8 新特性
前言
近些年來,JAVA技術發展受到嚴峻的挑戰,新型的Python語言,Go語言,機器學習語言都在向JAVA的霸主地位發起挑戰,誰能夠在這個時代更高效的完成項目開發迭代,更好的適應技術的發展,誰就能逐步佔領市場。JAVA被收購後,其開發團隊不斷尋求新的技術理念思想,融入新的概念,從而使得JAVA近來的更新變得更爲頻繁,也增加了許多新的技術特點,來迎接新的技術開發特性,維護自己的霸主地位。
下面就是比較詳細的JAVA 8 新特性展示圖
一、Lambda表達式
“->” , 該操作符被稱爲 Lambda 操作符或箭頭操作符。它將 Lambda 分爲兩個部分:
左邊:lambda形參列表的參數類型可以省略(類型推斷);如果lambda形參列表只有一個參數,其一對()也可以省略。
右邊:lambda體應該使用一對{}包裹;如果lambda體只有一條執行語句(可能是return語句),省略這一對{}和return關鍵字。
Lambda 表達式:語法
二、函數式(Functional)接口
Java 內置四大核心函數式接口:
其他接口:
三、方法引用與構造器引用
四、強大的Stream API
注意:
① Stream 自己不會存儲元素。
② Stream 不會改變源對象。相反,他們會返回一個持有結果的新Stream。
③ Stream 操作是延遲執行的。這意味着他們會等到需要結果的時候才執行。
Stream 的操作三個步驟:
① 創建Stream的方式
② Stream 的中間操作
③ Stream 的終止操作
Collectors工具類
五、Optional類
附1:Optional使用代碼示例:
public class OptionalTest {
/*
Optional.of(T t) : 創建一個 Optional 實例,t必須非空;
Optional.empty() : 創建一個空的 Optional 實例
Optional.ofNullable(T t):t可以爲null
*/
@Test
public void test1(){
Girl girl = new Girl();
girl = null;
//of(T t):保證t是非空的
Optional<Girl> optionalGirl = Optional.of(girl);
}
@Test
public void test2(){
Girl girl = new Girl();
// girl = null;
//ofNullable(T t):t可以爲null
Optional<Girl> optionalGirl = Optional.ofNullable(girl);
System.out.println(optionalGirl);
//orElse(T t1):如果單前的Optional內部封裝的t是非空的,則返回內部的t.
//如果內部的t是空的,則返回orElse()方法中的參數t1.
Girl girl1 = optionalGirl.orElse(new Girl("趙麗穎"));
System.out.println(girl1);
}
public String getGirlName(Boy boy){
return boy.getGirl().getName();
}
@Test
public void test3(){
Boy boy = new Boy();
boy = null;
String girlName = getGirlName(boy);
System.out.println(girlName);
}
//優化以後的getGirlName():
public String getGirlName1(Boy boy){
if(boy != null){
Girl girl = boy.getGirl();
if(girl != null){
return girl.getName();
}
}
return null;
}
@Test
public void test4(){
Boy boy = new Boy();
boy = null;
String girlName = getGirlName1(boy);
System.out.println(girlName);
}
//使用Optional類的getGirlName():
public String getGirlName2(Boy boy){
Optional<Boy> boyOptional = Optional.ofNullable(boy);
//此時的boy1一定非空
Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪麗熱巴")));
Girl girl = boy1.getGirl();
Optional<Girl> girlOptional = Optional.ofNullable(girl);
//girl1一定非空
Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
return girl1.getName();
}
@Test
public void test5(){
Boy boy = null;
boy = new Boy();
boy = new Boy(new Girl("蒼老師"));
String girlName = getGirlName2(boy);
System.out.println(girlName);
}
}
附2:Lambda表達式的使用
public class LambdaTest1 {
//語法格式一:無參,無返回值
@Test
public void test1(){
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("我愛北京天安門");
}
};
r1.run();
System.out.println("***********************");
Runnable r2 = () -> {
System.out.println("我愛北京故宮");
};
r2.run();
}
//語法格式二:Lambda 需要一個參數,但是沒有返回值。
@Test
public void test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("謊言和誓言的區別是什麼?");
System.out.println("*******************");
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("一個是聽得人當真了,一個是說的人當真了");
}
//語法格式三:數據類型可以省略,因爲可由編譯器推斷得出,稱爲“類型推斷”
@Test
public void test3(){
Consumer<String> con1 = (String s) -> {
System.out.println(s);
};
con1.accept("一個是聽得人當真了,一個是說的人當真了");
System.out.println("*******************");
Consumer<String> con2 = (s) -> {
System.out.println(s);
};
con2.accept("一個是聽得人當真了,一個是說的人當真了");
}
@Test
public void test4(){
ArrayList<String> list = new ArrayList<>();//類型推斷
int[] arr = {1,2,3};//類型推斷
}
//語法格式四:Lambda 若只需要一個參數時,參數的小括號可以省略
@Test
public void test5(){
Consumer<String> con1 = (s) -> {
System.out.println(s);
};
con1.accept("一個是聽得人當真了,一個是說的人當真了");
System.out.println("*******************");
Consumer<String> con2 = s -> {
System.out.println(s);
};
con2.accept("一個是聽得人當真了,一個是說的人當真了");
}
//語法格式五:Lambda 需要兩個或以上的參數,多條執行語句,並且可以有返回值
@Test
public void test6(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12,21));
System.out.println("*****************************");
Comparator<Integer> com2 = (o1,o2) -> {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(12,6));
}
//語法格式六:當 Lambda 體只有一條語句時,return 與大括號若有,都可以省略
@Test
public void test7(){
Comparator<Integer> com1 = (o1,o2) -> {
return o1.compareTo(o2);
};
System.out.println(com1.compare(12,6));
System.out.println("*****************************");
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(com2.compare(12,21));
}
@Test
public void test8(){
Consumer<String> con1 = s -> {
System.out.println(s);
};
con1.accept("一個是聽得人當真了,一個是說的人當真了");
System.out.println("*****************************");
Consumer<String> con2 = s -> System.out.println(s);
con2.accept("一個是聽得人當真了,一個是說的人當真了");
}
}
附3:java內置的4大核心函數式接口
public class LambdaTest2 {
@Test
public void test1(){
happyTime(500, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("學習太累了,去天上人間買了瓶礦泉水,價格爲:" + aDouble);
}
});
System.out.println("********************");
happyTime(400,money -> System.out.println("學習太累了,去天上人間喝了口水,價格爲:" + money));
}
public void happyTime(double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
List<String> list = Arrays.asList("北京","南京","天津","東京","西京","普京");
List<String> filterStrs = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("京");
}
});
System.out.println(filterStrs);
List<String> filterStrs1 = filterString(list,s -> s.contains("京"));
System.out.println(filterStrs1);
}
//根據給定的規則,過濾集合中的字符串。此規則由Predicate的方法決定
public List<String> filterString(List<String> list, Predicate<String> pre){
ArrayList<String> filterList = new ArrayList<>();
for(String s : list){
if(pre.test(s)){
filterList.add(s);
}
}
return filterList;
}
}
附4:構造器和數組引用
public class ConstructorRefTest {
//構造器引用
//Supplier中的T get()
//Employee的空參構造器:Employee()
@Test
public void test1(){
Supplier<Employee> sup = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println("*******************");
Supplier<Employee> sup1 = () -> new Employee();
System.out.println(sup1.get());
System.out.println("*******************");
Supplier<Employee> sup2 = Employee :: new;
System.out.println(sup2.get());
}
//Function中的R apply(T t)
@Test
public void test2(){
Function<Integer,Employee> func1 = id -> new Employee(id);
Employee employee = func1.apply(1001);
System.out.println(employee);
System.out.println("*******************");
Function<Integer,Employee> func2 = Employee :: new;
Employee employee1 = func2.apply(1002);
System.out.println(employee1);
}
//BiFunction中的R apply(T t,U u)
@Test
public void test3(){
BiFunction<Integer,String,Employee> func1 = (id,name) -> new Employee(id,name);
System.out.println(func1.apply(1001,"Tom"));
System.out.println("*******************");
BiFunction<Integer,String,Employee> func2 = Employee :: new;
System.out.println(func2.apply(1002,"Tom"));
}
//數組引用
//Function中的R apply(T t)
@Test
public void test4(){
Function<Integer,String[]> func1 = length -> new String[length];
String[] arr1 = func1.apply(5);
System.out.println(Arrays.toString(arr1));
System.out.println("*******************");
Function<Integer,String[]> func2 = String[] :: new;
String[] arr2 = func2.apply(10);
System.out.println(Arrays.toString(arr2));
}
}
附5:方法引用
public class MethodRefTest {
// 情況一:對象 :: 實例方法
//Consumer中的void accept(T t)
//PrintStream中的void println(T t)
@Test
public void test1() {
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("北京");
System.out.println("*******************");
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("beijing");
}
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2() {
Employee emp = new Employee(1001,"Tom",23,5600);
Supplier<String> sup1 = () -> emp.getName();
System.out.println(sup1.get());
System.out.println("*******************");
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
}
// 情況二:類 :: 靜態方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(12,21));
System.out.println("*******************");
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(12,3));
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4() {
Function<Double,Long> func = new Function<Double, Long>() {
@Override
public Long apply(Double d) {
return Math.round(d);
}
};
System.out.println("*******************");
Function<Double,Long> func1 = d -> Math.round(d);
System.out.println(func1.apply(12.3));
System.out.println("*******************");
Function<Double,Long> func2 = Math::round;
System.out.println(func2.apply(12.6));
}
// 情況三:類 :: 實例方法 (有難度)
// Comparator中的int comapre(T t1,T t2)
// String中的int t1.compareTo(t2)
@Test
public void test5() {
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","abd"));
System.out.println("*******************");
Comparator<String> com2 = String :: compareTo;
System.out.println(com2.compare("abd","abm"));
}
//BiPredicate中的boolean test(T t1, T t2);
//String中的boolean t1.equals(t2)
@Test
public void test6() {
BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
System.out.println(pre1.test("abc","abc"));
System.out.println("*******************");
BiPredicate<String,String> pre2 = String :: equals;
System.out.println(pre2.test("abc","abd"));
}
// Function中的R apply(T t)
// Employee中的String getName();
@Test
public void test7() {
Employee employee = new Employee(1001, "Jerry", 23, 6000);
Function<Employee,String> func1 = e -> e.getName();
System.out.println(func1.apply(employee));
System.out.println("*******************");
Function<Employee,String> func2 = Employee::getName;
System.out.println(func2.apply(employee));
}
}
附6:Stream的實例化四種方式
public class StreamAPITest {
//創建 Stream方式一:通過集合
@Test
public void test1(){
List<Employee> employees = EmployeeData.getEmployees();
// default Stream<E> stream() : 返回一個順序流
Stream<Employee> stream = employees.stream();
// default Stream<E> parallelStream() : 返回一個並行流
Stream<Employee> parallelStream = employees.parallelStream();
}
//創建 Stream方式二:通過數組
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4,5,6};
//調用Arrays類的static <T> Stream<T> stream(T[] array): 返回一個流
IntStream stream = Arrays.stream(arr);
Employee e1 = new Employee(1001,"Tom");
Employee e2 = new Employee(1002,"Jerry");
Employee[] arr1 = new Employee[]{e1,e2};
Stream<Employee> stream1 = Arrays.stream(arr1);
}
//創建 Stream方式三:通過Stream的of()
@Test
public void test3(){
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
}
//創建 Stream方式四:創建無限流
@Test
public void test4(){
// 迭代
// public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
//遍歷前10個偶數
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
// 生成
// public static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
}