Java 代碼精簡之道 (下)

1.利用 Optional

在 Java 8 裏,引入了一個 Optional 類,該類是一個能夠爲 null 的容器對象。算法

1.1.保證值存在設計模式

構造方法,能夠簡化對象的初始化和設置屬性操做。對於屬性字段較少的類,能夠自定義構造方法。app

普通:框架

Integer thisValue;
if (Objects.nonNull(value)) {
    thisValue = value;
else {
    thisValue = DEFAULT_VALUE;
}

精簡:ide

Integer thisValue = Optional.ofNullable(value).orElse(DEFAULT_VALUE);


1.2 保證值合法

普通:this

Integer thisValue;
if (Objects.nonNull(value) && value.compareTo(MAX_VALUE) <= 0) {
    thisValue = value;
else {
    thisValue = MAX_VALUE;
}

精簡:spa

Integer thisValue = Optional.ofNullable(value)
    .filter(tempValue -> tempValue.compareTo(MAX_VALUE) <= 0).orElse(MAX_VALUE);


1.3 
保證值合法
設計

普通:code

String zipcode = null;
if (Objects.nonNull(user)) {
    Address address = user.getAddress();
    if (Objects.nonNull(address)) {
        Country country = address.getCountry();
        if (Objects.nonNull(country)) {
            zipcode = country.getZipcode();
        }
    }
}

精簡:
orm

tring zipcode = Optional.ofNullable(user).map(User::getAddress)
    .map(Address::getCountry).map(Country::getZipcode).orElse(null);


2.利用 Stream

流(Stream)是Java 8的新成員,容許你以聲明式處理數據集合,能夠當作爲一個遍歷數據集的高級迭代器。流主要有三部分構成:獲取一個數據源→數據轉換→執行操做獲取想要的結果。每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象,這就容許對其操做能夠像鏈條同樣排列,造成了一個管道。流(Stream)提供的功能很是有用,主要包括匹配、過濾、彙總、轉化、分組、分組彙總等功能。

2.1.匹配集合數據

普通:

boolean isFound = false;
for (UserDO user : userList) {
    if (Objects.equals(user.getId(), userId)) {
        isFound = true;
        break;
    }
}

精簡:

boolean isFound = userList.stream()
    .anyMatch(user -> Objects.equals(user.getId(), userId));


2.2.過濾集合數據

普通:

List<UserDO> resultList = new ArrayList<>();
for (UserDO user : userList) {
    if (Boolean.TRUE.equals(user.getIsSuper())) {
        resultList.add(user);
    }
}

精簡:

List<UserDO> resultList = userList.stream()
    .filter(user -> Boolean.TRUE.equals(user.getIsSuper()))
    .collect(Collectors.toList());


2.3.彙總集合數據

普通:

double total = 0.0D;
for (Account account : accountList) {
    total += account.getBalance();
}

精簡:

double total = accountList.stream().mapToDouble(Account::getBalance).sum();


2.4.轉化集合數據

普通:

List<UserVO> userVOList = new ArrayList<>();
for (UserDO userDO : userDOList) {
    userVOList.add(transUser(userDO));
}

精簡:

List<UserVO> userVOList = userDOList.stream()
    .map(this::transUser).collect(Collectors.toList());


2.5.分組集合數據

普通:

Map<Long, List<UserDO>> roleUserMap = new HashMap<>();
for (UserDO userDO : userDOList) {
    roleUserMap.computeIfAbsent(userDO.getRoleId(), key -> new ArrayList<>())
        .add(userDO);
}

精簡:

Map<Long, List<UserDO>> roleUserMap = userDOList.stream()
    .collect(Collectors.groupingBy(UserDO::getRoleId));


2.6.分組彙總集合

普通:

Map<Long, Double> roleTotalMap = new HashMap<>();
for (Account account : accountList) {
    Long roleId = account.getRoleId();
    Double total = Optional.ofNullable(roleTotalMap.get(roleId)).orElse(0.0D);
    roleTotalMap.put(roleId, total + account.getBalance());
}

精簡:

roleTotalMap = accountList.stream().collect(Collectors.groupingBy(Account::getRoleId, Collectors.summingDouble(Account::getBalance)));


2.7.生成範圍集合
Python 的 range 很是方便,Stream 也提供了相似的方法。

普通:

int[] array1 = new int[N];
for (int i = 0; i < N; i++) {
    array1[i] = i + 1;
}

int[] array2 = new int[N];
array2[0] = 1;
for (int i = 1; i < N; i++) {
    array2[i] = array2[i - 1] * 2;
}

精簡:

int[] array1 = IntStream.rangeClosed(1, N).toArray();
int[] array2 = IntStream.iterate(1, n -> n * 2).limit(N).toArray();


3.利用程序結構

3.1.返回條件表達式

條件表達式判斷返回布爾值,條件表達式自己就是結果。

普通:

public boolean isSuper(Long userId)
    UserDO user 
= userDAO.get(userId);
    if (Objects.nonNull(user) && Boolean.TRUE.equals(user.getIsSuper())) {
        return true;
    }
    return false;
}

精簡:

public boolean isSuper(Long userId)
    UserDO user 
= userDAO.get(userId);
    return Objects.nonNull(user) && Boolean.TRUE.equals(user.getIsSuper());
}


3.2.最小化條件做用域

普通:

Result result = summaryService.reportWorkDaily(workDaily);
if (result.isSuccess()) {
    String message = "上報工做日報成功";
    dingtalkService.sendMessage(user.getPhone(), message);
else {
    String message = "上報工做日報失敗:" + result.getMessage();
    log.warn(message);
    dingtalkService.sendMessage(user.getPhone(), message);
}

精簡:

String message;
Result result = summaryService.reportWorkDaily(workDaily);
if (result.isSuccess()) {
    message = "上報工做日報成功";
else {
    message = "上報工做日報失敗:" + result.getMessage();
    log.warn(message);
}
dingtalkService.sendMessage(user.getPhone(), message);


3.3.調整表達式位置

調整表達式位置,在邏輯不變的前提下,讓代碼變得更簡潔。

普通:

String line = readLine();
while (Objects.nonNull(line)) {
    ... // 處理邏輯代碼
    line = readLine();
}

精簡:

for (String line = readLine(); Objects.nonNull(line); line = readLine()) {
    ... // 處理邏輯代碼
}


3.4.利用非空對象

普通:

private static final int MAX_VALUE = 1000;
boolean isMax = (value != null && value.equals(MAX_VALUE));
boolean isTrue = (result != null && result.equals(Boolean.TRUE));

精簡:

private static final Integer MAX_VALUE = 1000;
boolean isMax = MAX_VALUE.equals(value);
boolean isTrue = Boolean.TRUE.equals(result);


4.利用設計模式

模板方法模式(Template Method Pattern)定義一個固定的算法框架,而將算法的一些步驟放到子類中實現,使得子類能夠在不改變算法框架的狀況下重定義該算法的某些步驟。

4.1.模板方法模式

普通:

@Repository
public class UserValue {
    /** 值操做 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;
    /** 值模式 */
    private static final String KEY_FORMAT = "Value:User:%s";

    /** 設置值 */
    public void set(Long id, UserDO value) {
        String key = String.format(KEY_FORMAT, id);
        valueOperations.set(key, JSON.toJSONString(value));
    }

    /** 獲取值 */
    public UserDO get(Long id) {
        String key = String.format(KEY_FORMAT, id);
        String value = valueOperations.get(key);
        return JSON.parseObject(value, UserDO.class);
    }

    ...
}

@Repository
public class RoleValue {
    /** 值操做 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;
    /** 值模式 */
    private static final String KEY_FORMAT = "Value:Role:%s";

    /** 設置值 */
    public void set(Long id, RoleDO value) {
        String key = String.format(KEY_FORMAT, id);
        valueOperations.set(key, JSON.toJSONString(value));
    }

    /** 獲取值 */
    public RoleDO get(Long id) {
        String key = String.format(KEY_FORMAT, id);
        String value = valueOperations.get(key);
        return JSON.parseObject(value, RoleDO.class);
    }

    ...
}

精簡:

public abstract class AbstractDynamicValue<IV{
    /** 值操做 */
    @Resource(name = "stringRedisTemplate")
    private ValueOperations<String, String> valueOperations;

    /** 設置值 */
    public void set(I id, V value) {
        valueOperations.set(getKey(id), JSON.toJSONString(value));
    }

    /** 獲取值 */
    public V get(I id) {
        return JSON.parseObject(valueOperations.get(getKey(id)), getValueClass());
    }

    ...

    /** 獲取主鍵 */
    protected abstract String getKey(I id);

    /** 獲取值類 */
    protected abstract Class<V> getValueClass();
}

@Repository
public class UserValue extends AbstractValue<LongUserDO{
    /** 獲取主鍵 */
    @Override
    protected String getKey(Long id) {
        return String.format("Value:User:%s", id);
    }

    /** 獲取值類 */
    @Override
    protected Class<UserDO> getValueClass() {
        return UserDO.class;
    }
}

@Repository
public class RoleValue extends AbstractValue<LongRoleDO{
    /** 獲取主鍵 */
    @Override
    protected String getKey(Long id) {
        return String.format("Value:Role:%s", id);
    }

    /** 獲取值類 */
    @Override
    protected Class<RoleDO> getValueClass() {
        return RoleDO.class;    }} 
相關文章
相關標籤/搜索