Java從JDK8起提供了Stream流這個功能,于是項目里出現了大量基于Stream流的寫法。隨著項目的進行,慢慢的代碼中鋪天蓋地的都是下面的寫法:
List<User> userList = null;if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());}...省略了的業務邏輯...List<User> users = userList.stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());System.out.println(users);
上面的代碼中,構建了一個包含3個User對象的List,然后取出了其中age大于28的User對象構成了新的List。相信如果在日常工作和學習中寫過了大量的類似的代碼,很容易能看出問題來,userList會出現為空的情況,這時候是很容易觸發空指針異常的。所以我們在使用stream前通常都是需要做非空判斷的。于是,優化后的代碼出現了:
List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
if (userList != null) {List<User> users = userList.stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());System.out.println(users);
}
更近一步,還可以這樣寫:
List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
List<User> users = Optional.of(userList).orElse(List.of()).stream().filter(it-> it.getAge() > 28).collect(Collectors.toList());
System.out.println(users);
到了這里,這已經是一段比較常規的業務代碼了,但是它真的很丑有沒有。作為一個業務研發人員,我為什么要考慮這么多呢?我不需要關注List是怎么轉換成stream的,同樣的,我也不關心為什么在使用完stream以后還要collect。于是,我將上面的流式代碼封裝成了工具類,上面的代碼可以簡化為:
List<User> userList = null;
if (condition) {userList = new ArrayList<>();userList.add(User.builder().id(1L).name("張三").age(25).build());userList.add(User.builder().id(2L).name("李四").age(30).build());userList.add(User.builder().id(3L).name("王五").age(40).build());
}...省略了的業務邏輯...
List<User> users = Streams.filter(userList, it-> it.getAge() > 28);
System.out.println(users);
同樣的,也支持其他操作:
//返回年齡大于28的用戶列表
List<User> filterUsers = Streams.filter(userList, it -> it.getAge() > 28);//返回年齡大于28的用戶的姓名列表
List<String> filterNames = Streams.toList(userList, it -> it.getAge() > 28, User::getName);//返回年齡大于28的用戶的姓名作為key, 年齡只作為value的map
Map<String, Integer> filterNameAndAgeMap = Streams.toMap(userList, it -> it.getAge() > 28, User::getName, User::getAge);//返回所有用戶的姓名列表
List<String> allUserNames = Streams.toList(userList, User::getName);//返回所有用戶的姓名作為key, 用戶信息只作為value的map
Map<String, User> allUserMap = Streams.mappingToMap(userList, User::getName);//返回所有用戶的姓名作為key, 年齡作為value的map
Map<String, Integer> nameAndAgeMap = Streams.toMap(userList, User::getName, User::getAge);//返回年齡大于28的第一個用戶, 如果找不到則使用默認值
User user = Streams.findFirstOrElse(userList, it-> it.getAge() > 28, new User());//返回年齡大于28的第一個用戶, 如果找不到則拋出異常
User user2 = Streams.findFirstOrThrow(userList, it-> it.getAge() > 28, "未找到符合條件的數據");
最后附上工具類源碼供各位取用:
package com.zlyx.common.util;import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;public class Streams {public static <T> List<T> filter(List<T> dataList, Predicate<T> filter) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toList());}public static <T> Set<T> filter(Set<T> dataList, Predicate<T> filter) {return Optional.of(dataList).orElse(Set.of()).stream().filter(filter).collect(Collectors.toSet());}public static <T> T findFirstOrThrow(List<T> dataList) throws Exception {return findFirstOrThrow(dataList, "未找到符合條件的數據");}public static <T> T findFirstOrThrow(List<T> dataList, String errorMsg) throws Exception {return findFirstOrThrow(dataList, Objects::nonNull, errorMsg);}public static <T> T findFirstOrThrow(List<T> dataList, Predicate<T> filter, String errorMsg) throws Exception {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).findFirst().orElseThrow(() -> new Exception(errorMsg));}public static <T> T findFirstOrElse(List<T> dataList, T defaultValue) {return findFirstOrElse(dataList, Objects::nonNull, defaultValue);}public static <T> T findFirstOrElse(List<T> dataList, Predicate<T> filter, T defaultValue) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).findFirst().orElse(defaultValue);}public static <T, R> R findAnyOrNull(List<T> dataList, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().map(mapper).filter(Objects::nonNull).findAny().orElse(null);}public static <T, R> R findAnyOrThrow(List<T> dataList, Function<T, R> mapper, String errorMsg) throws Exception {return Optional.of(dataList).orElse(List.of()).stream().map(mapper).filter(Objects::nonNull).findAny().orElseThrow(() -> new Exception(errorMsg));}public static <T, R> Set<R> toSet(List<T> dataList, Function<T, R> mapper) {return toSet(dataList, Objects::nonNull, mapper);}public static <T, R> Set<R> toSet(List<T> dataList, Predicate<T> filter, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).map(mapper).collect(Collectors.toSet());}public static <T, R> List<R> toList(List<T> dataList, Function<T, R> mapper) {return toList(dataList, Objects::nonNull, mapper);}public static <T, R> List<R> toList(List<T> dataList, Predicate<T> filter, Function<T, R> mapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).map(mapper).distinct().collect(Collectors.toList());}public static <T, K> Map<K, T> mappingToMap(List<T> dataList, Function<T, K> keyMapper) {return mappingToMap(dataList, Objects::nonNull, keyMapper);}public static <T, K> Map<K, T> mappingToMap(List<T> dataList, Predicate<T> filter, Function<T, K> keyMapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toMap(keyMapper, it -> it, (v1, v2) -> v2));}public static <T, K, V> Map<K, V> toMap(List<T> dataList, Function<T, K> keyMapper, Function<T, V> valueMapper) {return toMap(dataList, Objects::nonNull, keyMapper, valueMapper);}public static <T, K, V> Map<K, V> toMap(List<T> dataList, Predicate<T> filter, Function<T, K> keyMapper, Function<T, V> valueMapper) {return Optional.of(dataList).orElse(List.of()).stream().filter(filter).collect(Collectors.toMap(keyMapper, valueMapper));}
}