减少查询数据库的频率,多在内存中计算

在一次请求中,网络IO占据了大多数的时间,代码在内存中的时间是很快的。有时候需要多次查询数据库,这时候可以将一个大的集合查询到,具体使用的时候在进行筛选。尤其避免了在for循环中多次调用数据库查询的情况。举例
错误示范

1
2
3
4
5
List<Pojo> collection = new ArrayList();
for (Pojo pojo : collection) {
Object o = repository.findById(pojo.getId());
xxx
}

正确示范

1
2
3
4
5
6
7
List<Pojo> collection = new ArrayList();
// 并不一定是全量查询,尽量缩小范围
List allData = repository.findAll();
for (Pojo pojo : collection) {
Optional data = allData.stream().filter(e -> Objects.equals(e.getId(), pojo.getId())).findFirst();
xxx
}

数据需要精确计算的场景下(如金额,率值,数据分析等)使用java.math.BigDecimal

推荐入参都使用Sring类型的,可以准确的获取预期值,尤其是浮点数,可能无法准确表示一个值,这与二进制有关,而我们使用的是十进制。例如0.1,当构造函数使用double时,传入的值不会正好等于0.1
出参也同样推荐BigDecimal,使用toPlainString()准确的表示。使用toString()可能会出现科学计数法的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 默认除法精度 */
private static final int DEFAULT_DIV_SCALE = 8;

public static BigDecimal div(String v1, String v2) {
return div(v1, v2, DEFAULT_DIV_SCALE);
}

public static BigDecimal div(String v1, String v2, int scale) {
if (NumberUtil.isNumber(v1) && NumberUtil.isNumber(v2) && new BigDecimal(v2).compareTo(BigDecimal.ZERO) > 0) {
return new BigDecimal(v1).divide(new BigDecimal(v2), scale, RoundingMode.HALF_UP);
}
return BigDecimal.ZERO;
}

使用枚举判断时,无需使用equals比较,直接使用==

直接使用==也避免了null的判断,枚举的equals实现也是直接==判断的,所以equals等同于==

1
2
3
4
5
6
/**
* Returns true if the specified object is equal to this enum constant.
*/
public final boolean equals(Object other) {
return this==other;
}

善用工具类

判断集合是否有元素
通常为list != null && list.size() > 0。可替换为!CollectionUtils.isEmpty(list)更加清晰
判断两个对象的值是否相等
需要判断不为空并且使用equals区比较。可替换为Objects.equals(a, b)
判断两个集合是否相等
许多工具类都提供了API,但并不好用,自己DIY的,也挺好使

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 判断集合是否相等
* 1.个数必须相等
* 2.元素必须相等
* 3.元素顺序可以不相等
*
* @param list1 集合1
* @param list2 集合2
* @return true表示元素相等
*/
public static <T>boolean isEqualList(List<T> list1, List<T> list2) {
if (list1 == null || list2 == null) {
return false;
}

if (list1.size() != list2.size()) {
return false;
}

Set<T> set1 = new HashSet<>(list1);
Set<T> set2 = new HashSet<>(list2);

return set1.containsAll(set2) && set2.containsAll(set1);
}