Java
这一页只放拿去改类名、字段名就能直接落地的 Java 模板,不放概念说明。
分页对象模板
java
@Data
public class PageQuery {
@Min(1)
private Integer pageNo = 1;
@Min(1)
@Max(200)
private Integer pageSize = 20;
public int getOffset() {
return (pageNo - 1) * pageSize;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageResult<T> {
private Long total;
private List<T> list;
public static <T> PageResult<T> empty() {
return new PageResult<>(0L, Collections.emptyList());
}
public static <T> PageResult<T> of(Long total, List<T> list) {
return new PageResult<>(total, list == null ? Collections.emptyList() : list);
}
}集合转换和去重
java
// List 提取字段,过滤 null,返回可修改集合
List<Long> idList = userList.stream()
.filter(Objects::nonNull)
.map(User::getId)
.filter(Objects::nonNull)
.collect(Collectors.toCollection(ArrayList::new));
// 逗号字符串转 Long 集合
List<Long> idList = Arrays.stream("1,2,3".split(","))
.map(String::trim)
.filter(s -> !s.isEmpty())
.map(Long::valueOf)
.collect(Collectors.toList());
// 按 id 去重,保留先出现的数据
List<User> distinctList = userList.stream()
.filter(Objects::nonNull)
.collect(Collectors.collectingAndThen(
Collectors.toMap(User::getId, Function.identity(), (first, ignored) -> first, LinkedHashMap::new),
map -> new ArrayList<>(map.values())
));
// 转逗号字符串
String ids = idList.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));List 转 Map 和分组
java
// key 重复时保留后面的值
Map<Long, User> userMap = userList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(User::getId, Function.identity(), (ignored, last) -> last));
// 按部门分组
Map<Long, List<User>> deptUserMap = userList.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(User::getDeptId));
// 分组后只保留姓名
Map<Long, List<String>> deptNameMap = userList.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(
User::getDeptId,
Collectors.mapping(User::getName, Collectors.toList())
));
// 分组计数
Map<Integer, Long> statusCountMap = userList.stream()
.collect(Collectors.groupingBy(User::getStatus, Collectors.counting()));树结构构建模板
java
@Data
public class MenuNode {
private Long id;
private Long parentId;
private String name;
private Integer sort;
private List<MenuNode> children = new ArrayList<>();
}
public static List<MenuNode> buildTree(List<MenuNode> source, Long rootParentId) {
if (source == null || source.isEmpty()) {
return Collections.emptyList();
}
Map<Long, MenuNode> nodeMap = source.stream()
.collect(Collectors.toMap(MenuNode::getId, Function.identity(), (first, ignored) -> first));
List<MenuNode> rootList = new ArrayList<>();
for (MenuNode node : source) {
if (Objects.equals(node.getParentId(), rootParentId)) {
rootList.add(node);
continue;
}
MenuNode parent = nodeMap.get(node.getParentId());
if (parent != null) {
parent.getChildren().add(node);
}
}
Comparator<MenuNode> comparator = Comparator.comparing(
MenuNode::getSort,
Comparator.nullsLast(Integer::compareTo)
);
sortTree(rootList, comparator);
return rootList;
}
private static void sortTree(List<MenuNode> nodes, Comparator<MenuNode> comparator) {
nodes.sort(comparator);
for (MenuNode node : nodes) {
if (node.getChildren() != null && !node.getChildren().isEmpty()) {
sortTree(node.getChildren(), comparator);
}
}
}BigDecimal 金额计算
java
// 累加金额,忽略 null
BigDecimal totalAmount = orderList.stream()
.map(Order::getAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 除法统一保留两位
BigDecimal avgAmount = totalAmount.divide(
BigDecimal.valueOf(orderList.size()),
2,
RoundingMode.HALF_UP
);
// 比较大小
if (payAmount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("支付金额必须大于 0");
}时间区间模板
java
LocalDate today = LocalDate.now();
// 当天:左闭右开
LocalDateTime beginTime = today.atStartOfDay();
LocalDateTime endTime = today.plusDays(1).atStartOfDay();
// 本周
LocalDate weekBegin = today.with(DayOfWeek.MONDAY);
LocalDate weekEnd = weekBegin.plusDays(7);
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String text = LocalDateTime.now().format(formatter);
// Date 和 LocalDateTime 互转
ZoneId zoneId = ZoneId.systemDefault();
Date date = Date.from(LocalDateTime.now().atZone(zoneId).toInstant());
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), zoneId);分批执行模板
java
public static <T> void batchConsume(List<T> source, int batchSize, Consumer<List<T>> consumer) {
if (source == null || source.isEmpty()) {
return;
}
if (batchSize <= 0) {
throw new IllegalArgumentException("batchSize must be greater than 0");
}
for (int i = 0; i < source.size(); i += batchSize) {
List<T> batch = source.subList(i, Math.min(i + batchSize, source.size()));
consumer.accept(batch);
}
}
batchConsume(orderIdList, 500, batch -> {
orderMapper.batchUpdateStatus(batch, 1);
});枚举缓存模板
java
@Getter
@AllArgsConstructor
public enum OrderStatus {
CREATED(1, "已创建"),
PAID(2, "已支付"),
CANCELED(9, "已取消");
private static final Map<Integer, OrderStatus> CACHE = Arrays.stream(values())
.collect(Collectors.toMap(OrderStatus::getCode, Function.identity()));
private final Integer code;
private final String text;
public static OrderStatus of(Integer code) {
return code == null ? null : CACHE.get(code);
}
}Optional 判空模板
java
String city = Optional.ofNullable(order)
.map(Order::getUser)
.map(User::getAddress)
.map(Address::getCity)
.orElse("");
User user = Optional.ofNullable(userMap.get(userId))
.orElseThrow(() -> new IllegalArgumentException("用户不存在:" + userId));CompletableFuture 并发查询模板
java
ExecutorService executor = Executors.newFixedThreadPool(8);
try {
CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(
() -> userService.getById(userId),
executor
);
CompletableFuture<List<Order>> orderFuture = CompletableFuture.supplyAsync(
() -> orderService.listByUserId(userId),
executor
);
CompletableFuture.allOf(userFuture, orderFuture).get(3, TimeUnit.SECONDS);
User user = userFuture.join();
List<Order> orderList = orderFuture.join();
} catch (TimeoutException e) {
throw new RuntimeException("查询超时", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("线程被中断", e);
} catch (ExecutionException e) {
throw new RuntimeException("并发查询失败", e.getCause());
} finally {
executor.shutdown();
}