Java 代码精简之道 (下)

1.利用 Optional

在 Java 8 里,引入了一个 Optional 类,该类是一个可以为 null 的容器对象。

1.1.保证值存在

构造方法,可以简化对象的初始化和设置属性操作。对于属性字段较少的类,可以自定义构造方法。

普通:

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

精简:

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


1.2 保证值合法

普通:

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

精简:

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


1.3 
保证值合法

普通:

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();
        }
    }
}

精简:

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;
    }


猜你喜欢

转载自blog.51cto.com/15057823/2632440