Java8 out 了嗎?

Java8 out 了嗎?

Java16已經橫空出世了,大家現在用的哪一版呢?不出所料,大多數都還在用Java8。

Oracle JDK 開始對 Java SE 8(8u201/202) 之後的版本進行商用收費,也就是說後續版本的JDK不再開源了,所以開源社群緊跟著推出了OpenJDK,

MariaDB(主要是擔心Oracle把Mysql也閉源了)等

替代備選方案。

一是JDK可能要面臨閉源,二是基於Java8的J2EE服務太龐大了,更換JDK不單單是要承受巨大的業務程式碼脫胎換骨般重構升級成本,還要承擔JDK升級不可預知的安全穩定性風險。

最新的未必就是最好的最實用的!這也就是Java持續盛行至今的一些原因吧。

既然大家都還在用Java8,那就簡單說說Java8的一些常用特性。

1。 Lambda表示式

JDK8之前繁瑣的

匿名內部類

,現在可以透過Lambda表示式(也稱閉包)簡潔高效地編碼實現,也稱函數語言程式設計。

orderDetails。forEach(

orderDetail -> orderDetail。setOrderId(order。getId()));etId()));

上面示例的程式碼可以顯示指定引數型別,如果Lambda表示式的函式體超過一行程式碼,可以加上花括號,如下:

orderDetails。forEach((OrderDetail orderDetail) -> { orderDetail。setOrderId(order。getId()); orderDetail。setCreateTime(order。getCreateTime());});

Lambda表示式,現在前後端開發基本都在用,前端有的叫箭頭函式。

2。 函式式介面

帶有 @FunctionalInterface 註解的介面類為函式式介面,僅起標記的作用,

可以隱式轉換為Lambda表示式。

函式式介面:只有一個普通函式的介面(預設方法及靜態方法除外)。

具有代表性的函式式介面有:

java。util。function。Function // 函式方法

java。util。function。Consumer // 消費者

java。util。function。Supplier // 提供者

java。util。function。Predicate // 斷言判斷

應用示例:

public static Map listToMap(List resources){ if(CollectionUtils。isNotEmpty(resources)){ return resources。stream()。collect( Collectors。toMap(D::getId, Function。identity(), (key1, key2) -> key2)); } return Collections。emptyMap();}

Function。identity() // 返回物件本身

(key1, key2) -> key2 // 表示當map的key重複時,value取最新值,即覆蓋處理

3。 介面預設方法及靜態方法

JDK8中對介面的功能做了擴充套件,以往只支援定義抽象方法,現在可以定義default修飾的預設方法及static修飾的靜態方法,下面各自舉例說明一下。

預設方法:

預設方法的功能可以被子類直接繼承使用,如果不能滿足子類功能,子類可以覆寫靜態方法。

public interface BaseRepository extends JpaSpecificationExecutor, JpaRepository { default Specification getSpecification(S example) { return (root, criteriaQuery, criteriaBuilder) -> { Path id = root。get(“id”); Path createTime = root。get(“createTime”); Path delFlag = root。get(“delFlag”); List predicateList = new ArrayList<>(); if (example。getId() != null && example。getId() > 0) { predicateList。add(criteriaBuilder。equal(id, example。getId())); } if (example。getDelFlag() != null) { predicateList。add(criteriaBuilder。equal(delFlag, example。getDelFlag())); } if (StringUtils。isNotEmpty(example。getFromDate())) { predicateList。add(criteriaBuilder。greaterThanOrEqualTo(createTime, DateUtil。parseYMDHMS(example。getFromDate() + “ 00:00:00”))); } if (StringUtils。isNotEmpty(example。getToDate())) { predicateList。add(criteriaBuilder。lessThanOrEqualTo(createTime, DateUtil。parseYMDHMS(example。getToDate() + “ 23:59:59”))); } return criteriaBuilder。and(predicateList。toArray(new Predicate[predicateList。size()])); }; }}

靜態方法:

子類可以直接呼叫,不能覆寫

@FunctionalInterfacepublic interface Function { static Function identity() { return t -> t; }}

4。 方法引用

HashMap> userActionMap = userActionList。stream()。collect( Collectors。groupingBy(UserAction::getBizId, HashMap::new, Collectors。mapping(UserAction::getUserId, Collectors。toSet())));

UserAction::getBizId // 成員方法引用

HashMap::new // 無參構造器引用,分組後用HashMap作為資料結果收集器

Collectors。groupingBy // 分組聚合,如本例的按userAction。bizId欄位分組

Collectors。mapping // 分組資料的value值對映處理,如本例取userAction。userId,存放到set集合

分組排序應用示例:

public static Map tokenize(String content){ if(StringUtils。isNotEmpty(content)){ List tokens = process(content); Map items = tokens。stream()。collect(Collectors。groupingBy(Function。identity(), Collectors。counting())); return items。entrySet()。stream()。sorted(Map。Entry。comparingByValue(Comparator。reverseOrder())) 。collect(Collectors。toMap(Map。Entry::getKey, Map。Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); } return Collections。emptyMap();}

5。 Stream 流式操作

List> userList = getUserByGroup();Predicate predicate = user -> StringUtils。isNotEmpty(user。getUserName());userList。stream()。filter(predicate)。flatMap(Collection::stream)。collect(Collectors。toList())

一些常用API說明:

filter:過濾

map:將函式轉為其他流或提取資訊

mapToInt:提取值,並轉為int型別;如:userList。mapToLong(User::getScore)。sum();

flatMap:返回一個stream,flatMap將流中的當前元素替換為此返回流拆解的流元素,如本例將List> 雙重集合拆分成扁平化流,流元素即為User物件

distinct:去重複

sorted:排序

limit:取前幾個;userList。stream()。limit(10)。collect(Collectors。toList());

skip:跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個,則返回一個空流。如:userList。stream()。skip(10)。collect(Collectors。toList());

collect:介面中的方法,定義瞭如何對流結果進行操作:如:。collect(Collectors。toList())

anyMatch:檢查至少一個匹配(返回型別boolean)

noneMatch:檢查是否沒有匹配的元素

findFirst:返回第一個結果(返回型別:Optional)

findAny:返回任意個結果

組合排序問題:

ComparaUser> comparator = Comparator。comparing(User::getScore,Comparator。nullsLast(Double::compareTo)) 。thenComparing(User::getUpdateTime,Comparator。nullsLast(Date::compareTo)) 。thenComparing(User::getId)。reversed();

Comparator。nullsLast 即空值元素排最後,reversed()表示逆序排列。

以上排序規則為:先按使用者積分倒序,積分相同的,按使用者更新時間倒序,更新時間也相同的,再按使用者ID倒序。

上述例子中,reversed()方法是作用於全欄位的,即score,updateTime,id 都倒序,如果在score或updateTime排序後再加上reversed()方法則為按score或updateTime升序排列(類似於負負得正)

未完待續。。。。。。

關注我,全棧開發,更多精彩分享!