Skip to content

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();
}
最近更新