1、lambda表達式
Lambda 是一個 匿名函數(shù),我們可以把 Lambda 表達式理解為是 一段可以傳遞的代碼(將代碼像數(shù)據(jù)一樣進行傳遞)。使用它可以寫出更簡潔、更靈活的代碼。
(1)語法
Lambda 表達式:在Java 8 語言中引入的一種新的語法元素和操作符。這個操作符為 “->” , 該操作符被稱為 Lambda操作符或 箭頭操作符。它將 Lambda 分為兩個部分:
左側(cè):指定了 Lambda 表達式需要的參數(shù)列表
右側(cè):指定了 Lambda 體,是抽象方法的實現(xiàn)邏輯,也即Lambda 表達式要執(zhí)行的功能。
語法格式一 : 無參,無返回值
Rannable r1 = () -> {System.out.println("Hello Lanbda !");}
語法格式二: :Lambda 需要一個參數(shù),但是沒有返回值。
Cousumer<String> con = (String str) -> {System.out.println("str");}
語法格式三 : 數(shù)據(jù)類型可以省略 ,因為可由編譯器推斷得出,稱為“類型推斷”
Cousumer<String> con = (str) -> {System.out.println("str");}
語法格式四: :Lambda 若只需要一個參數(shù)時, 參數(shù)的小括號可以省略
Cousumer<String> con = str -> {System.out.println("str");}
語法格式五: :Lambda 需要兩個或以上的參數(shù),多條執(zhí)行語句,并且可以有返回值
Comparator<Integer> com = (x,y) -> { System.out.println("實現(xiàn)函數(shù)式接口方法"); return Integer.compare(x,y); }
語法格式六 :當Lambda 體只有一條語句時,return與大括號若有,都可以省略
Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
(2)類型推斷
Lambda表達式中無需指定類型,程序依然可以編譯,這是因為 javac 根據(jù)程序的上下文,在后臺推斷出了參數(shù)的類型。Lambda 表達式的類型依賴于上下文環(huán)境,是由編譯器推斷出來的。這就是所謂的“類型推斷”。
(3)應用示例
// 1.創(chuàng)建線程
new Thread(() -> {
// method run,do something
}, "threadName").start();
// 2.匿名類
JButton show = new JButton("show");
show.addActionListener(e -> {
// method actionPerformed()
});
// 3.forEach迭代
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(System.out::println);
// 4.map 和reduce
List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500, 600);
costBeforeTax.stream().map(e -> e + 0.12 * e).forEach(System.out::print);
double bill = costBeforeTax.stream().map(e -> e + 0.12 * e)
.reduce((sum, cost) -> sum + cost).get();
System.out.println(bill);
// 5.過濾 filter 收集 collect
List<String> strs = Arrays.asList("abc", "defg", "hi", "jkmln");
List<String> filtered = strs.stream().filter(e -> e.length() > 2).collect(Collectors.toList());
// 6.去重
List<Integer> nums = Arrays.asList(1 ,2, 3, 1, 4, 5, 2, 6, 8, 7, 6);
nums = nums.stream().distinct().collect(Collectors.toList());
// 7.計算最大值、最小值、平均值、總和
List<Integer> primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
IntSummaryStatistics stats = primes.stream().mapToInt(e -> e).summaryStatistics();
System.out.println("最大值:" + stats.getMax());
System.out.println("最小值:" + stats.getMin());
System.out.println("平均值:" + stats.getAverage());
System.out.println("總和:" + stats.getSum());
System.out.println("計數(shù):" + stats.getCount());
(4)限制
lambda表達式有個限制,只能引用final和final局部變量,也就是說不能再lambda表達式內(nèi)部修改定義再域外的變量。否則編譯報錯:
2、函數(shù)式(Functional)接口
只包含一個抽象方法的接口,稱為 函數(shù)式接口。
Lambda表達式就是一個函數(shù)式接口的實例。匿名實現(xiàn)類表示的現(xiàn)在都可以用Lambda表達式來寫。
java內(nèi)置四大核心函數(shù)式接口:
3、方法引用與構(gòu)造器引用
? 當要傳遞給Lambda體的操作,已經(jīng)有實現(xiàn)的方法了,可以使用方法引用!
? 方法引用可以看做是Lambda表達式深層次的表達。換句話說,方法引用就是Lambda表達式,也就是函數(shù)式接口的一個實例,通過方法的名字來指向一個方法,可以認為是Lambda表達式的一個語法糖。
? 要求:實現(xiàn)接口的抽象方法的參數(shù)列表和返回值類型,必須與方法引用的方法的參數(shù)列表和返回值類型保持一致!
? 格式:使用操作符 “::” 將類(或?qū)ο?與方法名分隔開來。如下三種主要使用情況:
對象::實例方法名
類::靜態(tài)方法名
類::實例方法
// 方法引用 ClassName::methodName
如: Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
等同于: Comparator<Integer> com = Integer::compare;
// 構(gòu)造器引用 ClassName::new
如: Function<Integer, MyClass> fun = (n) -> new MyClass(n);
等同于: Function<Integer, MyClass> fun = MyClass::new;
//數(shù)組引用 type[] :: new
如: Function<Integer, Integer[]) fun = (n) -> new Integer[n];
等同于: Function<Integer, Integer[]) fun = Integer::new;
4、Stream API
Stream 和 Collection 集合的區(qū)別:Collection 是一種靜態(tài)的內(nèi)存數(shù)據(jù)結(jié)構(gòu),而 Stream 是有關(guān)計算的。前者是主要面向內(nèi)存,存儲在內(nèi)存中,后者主要是面向 CPU,通過 CPU 實現(xiàn)計算。
①Stream 自己不會存儲元素。
②Stream 不會改變源對象。相反,他們會返回一個持有結(jié)果的新Stream。
③Stream 操作是延遲執(zhí)行的。這意味著他們會等到需要結(jié)果的時候才執(zhí)行。
Stream操作的三個步驟:
創(chuàng)建Stream -> 中間操作 -> 終止操作(終端操作)
(1)創(chuàng)建Stream
// 方式1:通過集合
//Java8 中的 Collection 接口被擴展,提供了兩個獲取流的方法:
default Stream<E> stream() : 返回一個順序流
default Stream<E> parallelStream() : 返回一個并行流
例:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> integerStream = list.stream();
// 方式2:通過數(shù)組
// Java8 中的 Arrays 的靜態(tài)方法 stream() 可以獲取數(shù)組流:
static <T> Stream<T> stream(T[] array): 返回一個流
重載形式,能夠處理對應基本類型的數(shù)組:
public static IntStream stream(int[] array)
public static LongStream stream(long[] array)
public static DoubleStream stream(double[] array)
例: IntStream stream = Arrays.stream(new int[]{1, 2, 3, 4, 5});
// 方式3:通過Stream的of()
public static<T> Stream<T> of(T... values) // 接收任意可變參數(shù),返回一個流
例: Stream<String> stringStream = Stream.of("AA", "BB", "CC");
// 方式4: 創(chuàng)建無限流
>迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) >
生成 public static<T> Stream<T> generate(Supplier<T> s)
例:
// 迭代
Stream<Integer> stream = Stream.iterate(0, x -> x + 2); stream.limit(10).forEach(System.out::println);
// 生成
Stream<Double> stream1 = Stream.generate(Math::random); stream1.limit(10).forEach(System.out::println);
(2)Stream的中間操作
(2.1)篩選與切片
Person p1 = new Person("tom", 11);
Person p2 = new Person("jerry", 8);
Person p3 = new Person("marry", 5);
Person p4 = new Person("john", 14);
ArrayList<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
// 過濾
List<Person> collect = list.stream() .filter(p -> p.getAge() > 10).collect(Collectors.toList());
// 去重
Person p5 = new Person("john", 14);
collect = list.stream() .distinct() .collect(Collectors.toList());
// 截斷
collect = list.stream() .limit(2) .collect(Collectors.toList());
// 跳過元素
collect = list.stream() .skip(2) .collect(Collectors.toList());
(2.2)映射
List<String> nameList = list.stream()
.map(Person::getName)
.collect(Collectors.toList()); // map()和flatMap類似于集合的add()和addAll(),后者會展開元素
(2.3)排序
// 自定義比較
List<Person> sortedList = list.stream() .sorted((e1, e2) -> e1.getAge()-e2.getAge()) .collect(Collectors.toList());
// 數(shù)值的比較方法
sortedList = list.stream() .sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())) .collect(Collectors.toList());
// Comparator的靜態(tài)比較方法
sortedList = list.stream() .sorted(Comparator.comparingInt(Person::getAge)) .collect(Collectors.toList());
(3)Stream的終止操作
(3.1)匹配與查找
boolean allMatch = list.stream().allMatch(e -> e.getAge() > 10);
Optional<Person> first = list.stream().findFirst();
list.stream().filter(e -> e.getAge() > 10).count();
Optional<Person> max = list.stream() .filter(e -> e.getAge() > 10) .max(Comparator.comparingInt(Person::getAge));
list.stream().filter(e -> e.getAge() > 10).forEach(System.out::println);
(3.2)歸約
Optional<Integer> reduce = list.stream() .map(Person::getAge) .reduce((e1, e2) -> e1 + e2);
(3.3)收集
(4)Collectors
5、Optional類
Optional<T> 類(java.util.Optional) 是一個容器類,它可以保存類型T的值,代表這個值存在。或者僅僅保存null,表示這個值不存在。原來用 null 表示一個值不存在,現(xiàn)在 Optional 可以更好的表達這個概念。并且可以避免空指針異常。
Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測。
創(chuàng)建Optional 類對象的方法:
? Optional.of(T t) : 創(chuàng)建一個 Optional 實例,t必須非空;
? Optional.empty() : 創(chuàng)建一個空的 Optional 實例
? Optional.ofNullable(T t) :t可以為null
判斷Optional 容器中是否包含對象:
? boolean isPresent() : 判斷是否包含對象
? void ifPresent(Consumer<? super T> consumer) :如果有值,就執(zhí)行Consumer接口的實現(xiàn)代碼,并且該值會作為參數(shù)傳給它。
獲取Optional 容器的對象:
? T get(): 如果調(diào)用對象包含值,返回該值,否則拋異常
? T orElse(T other) :如果有值則將其返回,否則返回指定的other對象。
? T orElseGet(Supplier<? extends T> other) : :如果有值則將其返回,否則返回由Supplier接口實現(xiàn)提供的對象。
? T orElseThrow(Supplier<? extends X> exceptionSupplier) : :如果有值則將其返文章來源:http://www.zghlxwxcb.cn/news/detail-697890.html
回,否則拋出由Supplier接口實現(xiàn)提供的異常。文章來源地址http://www.zghlxwxcb.cn/news/detail-697890.html
//使用Optional類的getGirlName():
public String getGirlName2(Boy boy){
Optional boyOptional = Optional.ofNullable(boy);
//此時的boy1一定非空
Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪麗熱巴")));
Girl girl = boy1.getGirl();
Optional girlOptional = Optional.ofNullable(girl);
//girl1一定非空
Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
return girl1.getName();
}
到了這里,關(guān)于java8 新特性的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!