原文地址http://blog.csdn.net/myherux/article/details/52717492
(一)optional類
-
創(chuàng)建一個空Optional對象
輸出的是一個空的
optional對象Optional<String> optional = Optional.empty(); System.out.println(optional); ##:Optional.empty -
創(chuàng)建一個非空Optional對象
如果
person是null,將會立即拋出,而不是訪問person的屬性時獲得一個潛在的錯誤Person person = new Person("xu","hua"); Optional<Person> optional2 = Optional.of(person); System.out.println(optional2); System.out.println(optional2.get()); System.out.println(optional2.get().firstName); ##:Optional[xuhua] xuhua xu -
判斷對象是否存在
System.out.println(optional.isPresent()); System.out.println(optional2.isPresent()); ##:false true -
如果Optional為空返回默認(rèn)值
System.out.println(optional.orElse("fallback")); optional.ifPresent(System.out::println); ##:fallback xuhua
(二)Lambda表達(dá)式
-
Lambda表達(dá)式的使用
java8以前的字符串排列,創(chuàng)建一個匿名的比較器對象
Comparator然后將其傳遞給sort方法
```
List<String> names= Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return b.compareTo(a);
}
});
```
`java8`使用`lambda`表達(dá)式就不需要匿名對象了
```
Collections.sort(names,(String a,String b)->{return b.compareTo(a);});
```
簡化一下:對于函數(shù)體只有一行代碼的,你可以去掉大括號{}以及`return`關(guān)鍵字
```
Collections.sort(names,(String a,String b)->b.compareTo(a));
```
`Java`編譯器可以自動推導(dǎo)出參數(shù)類型,所以你可以不用再寫一次類型
```
Collections.sort(names, (a, b) -> b.compareTo(a));
```
```
##:[xenia, peter, mike, anna]
```
對于`null`的處理
```
List<String> names2 = Arrays.asList("peter", null, "anna", "mike", "xenia");
names2.sort(Comparator.nullsLast(String::compareTo));
System.out.println(names2);
##:[anna, mike, peter, xenia, null]
```
-
函數(shù)式接口,方法,構(gòu)造器
每一個
lambda表達(dá)式都對應(yīng)一個類型,通常是接口類型。而“函數(shù)式接口”是指僅僅只包含一個抽象方法的接口,每一個該類型的
lambda表達(dá)式都會被匹配到這個抽象方法。因為默認(rèn)方法不算抽象方法,所以你也可以給你的函數(shù)式接口添加默認(rèn)方法。
我們可以將
lambda表達(dá)式當(dāng)作任意只包含一個抽象方法的接口類型,確保你的接口一定達(dá)到這個要求,你只需要給你的接口添加
@FunctionalInterface注解,編譯器如果發(fā)現(xiàn)你標(biāo)注了這個注解的接口有多于一個抽象方法的時候會報錯的。
-
函數(shù)式接口
@FunctionalInterface public static interface Converter<F, T> { T convert(F from); } /**原始的接口實現(xiàn)*/ Converter<String, Integer> integerConverter1 = new Converter<String, Integer>() { @Override public Integer convert(String from) { return Integer.valueOf(from); } }; /**使用lambda表達(dá)式實現(xiàn)接口*/ Converter<String, Integer> integerConverter2 = (from) -> Integer.valueOf(from); Integer converted1 = integerConverter1.convert("123"); Integer converted2 = integerConverter2.convert("123"); System.out.println(converted1); System.out.println(converted2); ##:123 123 /**簡寫的lambda表達(dá)式*/ Converter<String, Integer> integerConverter3 = Integer::valueOf; Integer converted3 = integerConverter3.convert("123"); System.out.println(converted3); ##:123 -
函數(shù)式方法
static class Something { String startsWith(String s) { return String.valueOf(s.charAt(0)); } } Something something = new Something(); Converter<String, String> stringConverter = something::startsWith; String converted4 = stringConverter.convert("Java"); System.out.println(converted4); ##:j -
函數(shù)式構(gòu)造器
Java編譯器會自動根據(jù)PersonFactory.create方法的簽名來選擇合適的構(gòu)造函數(shù)。
public class Person { public String firstName; public String lastName; public Person() { } public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String toString(){ return firstName+lastName; } }interface PersonFactory<P extends Person> { P create(String firstName, String lastName); } PersonFactory<Person> personFactory = Person::new; Person person = personFactory.create("xu", "hua"); System.out.println(person.toString()); ##:xuhua
-
-
Lambda作用域
在lambda表達(dá)式中訪問外層作用域和老版本的匿名對象中的方式很相似。
你可以直接訪問標(biāo)記了final的外層局部變量,或者實例的字段以及靜態(tài)變量。
static int outerStaticNum = 10; int outerNum; void testScopes() { /**變量num可以不用聲明為final*/ int num = 1; /**可以直接在lambda表達(dá)式中訪問外層的局部變量*/ Lambda2.Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + outerStaticNum+num); String convert = stringConverter.convert(2); System.out.println(convert); ##:13 /**但是num必須不可被后面的代碼修改(即隱性的具有final的語義),否則編譯出錯*/ //num=3; /**lambda內(nèi)部對于實例的字段以及靜態(tài)變量是即可讀又可寫*/ Lambda2.Converter<Integer, String> stringConverter2 = (from) -> { outerNum = 13; return String.valueOf(from + outerNum); }; System.out.println(stringConverter2.convert(2)); System.out.println("\nBefore:outerNum-->" + outerNum); outerNum = 15; System.out.println("After:outerNum-->" + outerNum); ##:Before:outerNum-->13 After:outerNum-->15 String[] array = new String[1]; Lambda2.Converter<Integer, String> stringConverter3 = (from) -> { array[0] = "Hi here"; return String.valueOf(from); }; stringConverter3.convert(23); System.out.println("\nBefore:array[0]-->" + array[0]); array[0] = "Hi there"; System.out.println("After:array[0]-->" + array[0]); ##:Before:array[0]-->Hi here After:array[0]-->Hi there }
(三)Stream類
java.util.Stream 表示能應(yīng)用在一組元素上一次執(zhí)行的操作序列。
Stream 操作分為中間操作或者最終操作兩種,最終操作返回一特定類型的計算結(jié)果,而中間操作返回Stream本身,這樣你就可以將多個操作依次串起來。
Stream 的創(chuàng)建需要指定一個數(shù)據(jù)源,比如 java.util.Collection的子類,List或者Set,Map不支持。
Stream的操作可以串行執(zhí)行或者并行執(zhí)行。
-
Stream的基本接口
List<String> stringCollection = new ArrayList<>(); stringCollection.add("ddd2"); stringCollection.add("aaa2"); stringCollection.add("bbb1"); stringCollection.add("aaa1"); stringCollection.add("bbb3"); stringCollection.add("ccc"); stringCollection.add("bbb2"); stringCollection.add("ddd1");-
Filter 過濾.
Filter通過一個predicate接口來過濾并只保留符合條件的元素,該操作屬于中間操作,所以我們可以在過濾后的結(jié)果來應(yīng)用其他Stream操作(比如forEach)。forEach需要一個函數(shù)來對過濾后的元素依次執(zhí)行。forEach是一個最終操作,所以我們不能在forEach之后來執(zhí)行其他Stream操作。stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println); -
Sorted 排序.
Sorted是一個中間操作,返回的是排序好后的Stream。如果你不指定一個自定義的
Comparator則會使用默認(rèn)排序.stringCollection .stream() .sorted() .forEach(System.out::println); System.out.println(stringCollection);//原數(shù)據(jù)源不會被改變 -
Map.
中間操作
map會將元素根據(jù)指定的Function接口來依次將元素轉(zhuǎn)成另外的對象.stringCollection .stream() .map(String::toUpperCase) .map((s)->s+" space") .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println); -
Match
Stream提供了多種匹配操作,允許檢測指定的Predicate是否匹配整個Stream。所有的匹配操作都是最終操作,并返回一個boolean類型的值。
boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a")); System.out.println(anyStartsWithA); // true boolean allStartsWithA = stringCollection .stream() .allMatch((s) -> s.startsWith("a")); System.out.println(allStartsWithA); // false boolean noneStartsWithZ = stringCollection .stream() .noneMatch((s) -> s.startsWith("z")); System.out.println(noneStartsWithZ); // true -
Count
計數(shù)是一個最終操作,返回
Stream中元素的個數(shù),返回值類型是long。long startsWithB = stringCollection .stream() .filter((s) -> s.startsWith("b")) .count(); System.out.println(startsWithB); // 3 -
Reduce
Reduce是一個最終操作,允許通過指定的函數(shù)來講stream中的多個元素規(guī)約為一個元素,規(guī)約后的結(jié)果是通過Optional接口表示的。Optional<String> reduced = stringCollection .stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2); reduced.ifPresent(System.out::println); ##:aaa1#aaa2#bbb1#bbb2#bbb3#ccc#ddd1#ddd2
-
-
并行stream和串行stream
-
串行stream
List<String> values = new ArrayList<>(MAX); for (int i = 0; i < MAX; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t0 = System.nanoTime(); long count = values.stream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("sequential sort took: %d ms", millis)); -
并行stream
并行
stream是在運(yùn)行時將數(shù)據(jù)劃分成了多個塊,然后將數(shù)據(jù)塊分配給合適的處理器去處理。只有當(dāng)所有塊都處理完成了,才會執(zhí)行之后的代碼。
List<String> values = new ArrayList<>(MAX); for (int i = 0; i < MAX; i++) { UUID uuid = UUID.randomUUID(); values.add(uuid.toString()); } long t0 = System.nanoTime(); long count = values.parallelStream().sorted().count(); System.out.println(count); long t1 = System.nanoTime(); long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0); System.out.println(String.format("parallel sort took: %d ms", millis));時間結(jié)果比較:
1000000 sequential sort took: 717 ms 1000000 parallel sort took: 303 ms
-
-
IntStream接口
IntStream接口是stream的一種,繼承了BaseStream接口。- range
IntStream.range(0, 10) .forEach(i -> { if (i % 2 == 1) System.out.print(i+" "); }); ##:1 3 5 7 9 OptionalInt reduced1 = IntStream.range(0, 10) .reduce((a, b) -> a + b); System.out.println(reduced1.getAsInt()); int reduced2 = IntStream.range(0, 10) .reduce(7, (a, b) -> a + b); System.out.println(reduced2); ##:45 52 - sum
System.out.println(IntStream.range(0, 10).sum());
- range
-
Stream的應(yīng)用
Map<String, Integer> unsortMap = new HashMap<>(); unsortMap.put("z", 10); unsortMap.put("b", 5); unsortMap.put("a", 6); unsortMap.put("c", 20); unsortMap.put("d", 1); unsortMap.put("e", 7); unsortMap.put("y", 8); unsortMap.put("n", 99); unsortMap.put("j", 50); unsortMap.put("m", 2); unsortMap.put("f", 9);使用
stream類來對map的value排序public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) { Map<K, V> result = new LinkedHashMap<>(); map.entrySet().parallelStream() .sorted((o1, o2) -> (o2.getValue()).compareTo(o1.getValue())) .forEachOrdered(x -> result.put(x.getKey(), x.getValue())); return result; } System.out.println(sortByValue(unsortMap)); ##:{n=99, j=50, c=20, z=10, f=9, y=8, e=7, a=6, b=5, m=2, d=1}List<Object> list = new ArrayList<>(); JSONObject data1 = new JSONObject(); data1.put("type", "支出"); data1.put("money", 500); JSONObject data2 = new JSONObject(); data2.put("type", "收入"); data2.put("money", 1000); JSONObject data3 = new JSONObject(); data3.put("type", "借貸"); data3.put("money", 100); list.add(data1); list.add(data2); list.add(data3);使用
stream類來處理list``里面的json`數(shù)據(jù)/** * 按money的值來排列json */ list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("money")) .sorted((b, a) -> Integer.valueOf(JSONObject.fromObject(a).getInt("money")).compareTo(JSONObject.fromObject(b) .getInt("money"))) .forEach(System.out::println); /** * 找到最小的money */ Integer min = list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("money")) .map(x -> JSONObject.fromObject(x).getInt("money")) .sorted() .findFirst() .get(); System.out.println(min); /** * 計算type的數(shù)目 */ Map<String, Integer> type_count = new HashMap<>(); list.stream() .filter(x -> JSONObject.fromObject(x).containsKey("type")) .map(x -> JSONObject.fromObject(x).getString("type")) .forEach(x -> { if (type_count.containsKey(x)) type_count.put(x, type_count.get(x) + 1); else type_count.put(x, 1); }); System.out.println(type_count.toString()); ##: {"type":"收入","money":1000} {"type":"支出","money":500} {"type":"借貸","money":100} 100 {借貸=1, 收入=1, 支出=1}