金融场景下BigDecimal 运算规范 + 常用场景使用 + 数据库字段设计详解

文章目录

  • 前言
    • [金融场景下BigDecimal 运算规范 + 常用场景使用 + 数据库字段设计详解](#金融场景下BigDecimal 运算规范 + 常用场景使用 + 数据库字段设计详解)
      • [1. 数据库方面](#1. 数据库方面)
      • [2. VO 接受](#2. VO 接受)
      • [3. 原生BigDecimal的核心痛点](#3. 原生BigDecimal的核心痛点)
      • [4. BigDecimal 与 BigInteger 的区别说明](#4. BigDecimal 与 BigInteger 的区别说明)
      • [5. 常用的使用方法](#5. 常用的使用方法)
        • [5.1. 金额转换](#5.1. 金额转换)
        • [5.2. 金额运算](#5.2. 金额运算)
        • [5.3. 金额批量聚合](#5.3. 金额批量聚合)
        • [5.4. 金额比较](#5.4. 金额比较)
        • [5.5. 金额判断](#5.5. 金额判断)
        • [5.6. 金额数值工具](#5.6. 金额数值工具)
        • [5.7. 金额格式化](#5.7. 金额格式化)
        • [5.8. 计算百分比](#5.8. 计算百分比)
        • [5.9. 判断金额是否有效](#5.9. 判断金额是否有效)

前言

  如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。

  而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!


金融场景下BigDecimal 运算规范 + 常用场景使用 + 数据库字段设计详解

1. 数据库方面

只要是跟钱、精度有关 ,一律用 DECIMAL:

DECIMAL = 高精度、无误差的小数类型。

格式:

bash 复制代码
DECIMAL(M,D)
* M = 总共多少位数字
* D = 小数点后保留几位

专门存:钱、金额、财务数据。

  • 通用金额(最常见):DECIMAL (10,2) 整数 8 位、小数 2 位:最大 99,999,999.99(近 1 亿)
  • 一般企业 / 电商:DECIMAL (12,2) 整数 10 位:最大 9,999,999,999.99(近 100 亿)
  • 超大金额 / 财务汇总:DECIMAL (17,2) 或 DECIMAL (18,2) 整数 15/16 位:999...999.99(万亿级别)

2. VO 接受

使用BigDecimal,BigDecimal 是金额唯一标准类型。

bash 复制代码
public class OrderVO {
    // 数据库 DECIMAL(17,2) → VO 用 BigDecimal
    private BigDecimal amount;
}

json样式示例:

bash 复制代码
{
  "amount": 123456789012345.67
}

3. 原生BigDecimal的核心痛点

  1. equals比较失效问题
    new BigDecimal("1.0").equals(new BigDecimal("1.00")) → false
    原因:equals 会比较数值+小数位数,业务上数值相等即可,必须用 compareTo。
  2. 舍入模式不统一,资损风险极大
    金融场景默认需要四舍五入(HALF_UP),但代币场景必须向下取整(DOWN),防止多给资产。
    项目中如果到处乱写舍入模式,会出现:对账不平、用户多提币、手续费计算错误等严重问题。
  3. DecimalFormat线程不安全
    全局复用 DecimalFormat 会导致高并发下格式化错乱、数字异常,绝大多数开源工具类都没解决这个问题。

注意的是直接使用 double 存金额,会出现浮点精度丢失。

4. BigDecimal 与 BigInteger 的区别说明

BigDecimal:适用于需要高精度的小数计算的场景,常用于法币金额的计算;

BigInteger:适用于需要处理非常大的整数的场景,常用于原始金额(如 Wei、Satoshi 等)的计算;

5. 常用的使用方法

5.1. 金额转换

1、String 转换 BigDecimal;

java 复制代码
public static BigDecimal of(String value) {
    // 检查 value 不能为 null,然后去掉前后空格
    String clean = Objects.requireNonNull(value, "金额不能为空").trim();
    if (clean.isEmpty()) {
        throw new IllegalArgumentException("金额不能为空字符串");
    }
    
    // 移除逗号,准备转换为 BigDecimal
    clean = clean.replace(",", "");

    // 禁止科学计数法输入,避免精度问题和意外结果
    // 检查金额里有没有出现科学计数法(比如 1E6、1.23e8)
    if (clean.contains("E") || clean.contains("e")) {
        throw new IllegalArgumentException("金额不支持科学计数法: " + value);
    }
    try {
        return new BigDecimal(clean);
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("非法的金额格式: " + value, e);
    }
}

2、long 转换 BigDecimal;

java 复制代码
public static BigDecimal of(long value) {
    return BigDecimal.valueOf(value);
}

3、double 转换 BigDecimal;

java 复制代码
public static BigDecimal of(double value) {
    return new BigDecimal(Double.toString(value));
}
5.2. 金额运算
java 复制代码
private static void checkNotNull(BigDecimal a, BigDecimal b) {
    // 检查参数 a 不能为 null
    Objects.requireNonNull(a, "参数 a 不能为空");
    // 检查参数 b 不能为 null
    Objects.requireNonNull(b, "参数 b 不能为空");
}

1、加法;

java 复制代码
public static BigDecimal add(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.add(b);
}

2、减法;

java 复制代码
public static BigDecimal subtract(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.subtract(b);
}

3、乘法;

java 复制代码
public static BigDecimal multiply(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.multiply(b);
}

4、除法;

java 复制代码
public static BigDecimal divide(
        BigDecimal a,
        BigDecimal b,
        int scale,
        RoundingMode roundingMode) {

    checkNotNull(a, b);
    Objects.requireNonNull(roundingMode, "舍入模式不能为空");
    if (scale < 0) {
        throw new IllegalArgumentException("scale 不能小于 0");
    }
    if (eqZero(b)) {
        throw new IllegalArgumentException("除数不能为 0");
    }
    return a.divide(b, scale, roundingMode);
}

5、乘法(舍入);

java 复制代码
public static BigDecimal multiply(
        BigDecimal a,
        BigDecimal b,
        int scale,
        RoundingMode roundingMode) {

    checkNotNull(a, b);
    Objects.requireNonNull(roundingMode, "舍入模式不能为空");
    if (scale < 0) {
        throw new IllegalArgumentException("scale 不能小于 0");
    }
    // 先乘法后舍入,避免中间结果过大导致的精度问题
    return a.multiply(b).setScale(scale, roundingMode);
}

6、除法(舍入);

java 复制代码
public static BigDecimal divideOrZero(
        BigDecimal a,
        BigDecimal b,
        int scale,
        RoundingMode roundingMode) {

    checkNotNull(a, b);
    if (eqZero(b)) {
        return BigDecimal.ZERO;
    }
    return divide(a, b, scale, roundingMode);
}
5.3. 金额批量聚合
java 复制代码
public static BigDecimal sum(Collection<BigDecimal> values) {
    if (values == null || values.isEmpty()) {
        return BigDecimal.ZERO;
    }
    // 使用流式 API 进行聚合,增加 null 过滤,避免潜在的 NullPointerException
    return values.stream()
            .filter(Objects::nonNull)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
}
5.4. 金额比较

1、相等比较方法;

java 复制代码
public static boolean eq(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.compareTo(b) == 0;
}

2、大于比较方法;

java 复制代码
public static boolean gt(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.compareTo(b) > 0;
}

3、大于等于比较方法;

java 复制代码
public static boolean ge(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.compareTo(b) >= 0;
}

4、小于比较方法;

java 复制代码
public static boolean lt(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.compareTo(b) < 0;
}

5、小于等于比较方法;

java 复制代码
public static boolean le(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.compareTo(b) <= 0;
}
5.5. 金额判断

1、判断金额是否大于 0;

java 复制代码
public static boolean gtZero(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    // 使用 compareTo 而不是 equals 来比较 BigDecimal 是否大于 0,避免 scale 不同导致的比较失败
    return amount.compareTo(BigDecimal.ZERO) > 0;
}

2、判断金额是否大于等于 0;

java 复制代码
public static boolean geZero(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    // 使用 compareTo 而不是 equals 来比较 BigDecimal 是否大于等于 0,避免 scale 不同导致的比较失败
    return amount.compareTo(BigDecimal.ZERO) >= 0;
}

3、判断金额是否等于 0;

java 复制代码
public static boolean eqZero(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    // 使用 compareTo 而不是 equals 来比较 BigDecimal 是否等于 0,避免 scale 不同导致的比较失败
    return amount.compareTo(BigDecimal.ZERO) == 0;
}

4、判断金额是否小于 0;

java 复制代码
public static boolean ltZero(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    // 使用 compareTo 而不是 equals 来比较 BigDecimal 是否小于 0,避免 scale 不同导致的比较失败
    return amount.compareTo(BigDecimal.ZERO) < 0;
}
5.6. 金额数值工具

1、获取两个金额中的较大值

场景说明:

获取两个金额中的较大值,注意 BigDecimal 的 max 方法会返回两个数中较大的一个。

注意它不会修改原有的 BigDecimal 对象,而是返回一个新的对象。

java 复制代码
public static BigDecimal max(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.max(b);
}

2、获取两个金额中的较小值

场景说明:

获取两个金额中的较小值,注意 BigDecimal 的 min 方法会返回两个数中较小的一个。

注意它不会修改原有的 BigDecimal 对象,而是返回一个新的对象。

java 复制代码
public static BigDecimal min(BigDecimal a, BigDecimal b) {
    checkNotNull(a, b);
    return a.min(b);
}

3、获取金额的绝对值

场景说明:

获取金额的绝对值,注意 BigDecimal 的 abs 方法会返回金额的绝对值。

注意它不会修改原有的 BigDecimal 对象,而是返回一个新的对象。

java 复制代码
public static BigDecimal abs(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    return amount.abs();
}

4、获取金额的相反数

场景说明:

获取金额的相反数,注意 BigDecimal 的 negate 方法会返回金额的相反数。

注意它不会修改原有的 BigDecimal 对象,而是返回一个新的对象。

java 复制代码
public static BigDecimal negate(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    return amount.negate();
}

5、将金额限制在一个范围内

场景说明:

将金额限制在一个范围内,如果金额小于最小值,则返回最小值。

如果金额大于最大值,则返回最大值;否则返回金额本身。

java 复制代码
public static BigDecimal clamp(BigDecimal value, BigDecimal min, BigDecimal max) {
    Objects.requireNonNull(value, "值不能为空");
    Objects.requireNonNull(min, "最小值不能为空");
    Objects.requireNonNull(max, "最大值不能为空");

    // 先检查 min 和 max 的关系,避免逻辑错误导致的异常情况
    // 如果 min 大于 max,说明参数传递有误,抛出 IllegalArgumentException 异常,提示调用方检查参数
    if (gt(min, max)) {
        throw new IllegalArgumentException("min 不能大于 max");
    }

    // 进行范围限制,如果 value 小于 min,则返回 min;如果 value 大于 max,则返回 max;否则返回 value 本身
    if (lt(value, min)) {
        return min;
    }
    // 进行范围限制,如果 value 大于 max,则返回 max;否则返回 value 本身
    if (gt(value, max)) {
        return max;
    }
    // 如果 value 在 min 和 max 之间,则直接返回 value 本身
    return value;
}

6,对金额进行舍入(自定义)

场景说明:

对金额进行舍入,注意 BigDecimal 的 setScale 方法会返回一个新对象(不会修改原有的 BigDecimal 对象)。

例如:对金额进行舍入,或者对金额进行小数位调整等场景,通常需要使用 setScale 方法来实现。

java 复制代码
public static BigDecimal roundToken(
        BigDecimal amount,
        int decimals,
        RoundingMode roundingMode) {

    Objects.requireNonNull(amount, "金额不能为空");
    Objects.requireNonNull(roundingMode, "舍入模式不能为空");
    // 对金额进行舍入,保留 decimals 位小数,并使用 roundingMode 来处理四舍五入
    if (decimals < 0) {
        throw new IllegalArgumentException("decimals 不能小于 0");
    }
    // 对金额进行舍入,保留 decimals 位小数,并使用 roundingMode 来处理四舍五入
    return amount.setScale(decimals, roundingMode);
}
5.7. 金额格式化

1、格式化金额为字符串(含货币符号)

场景说明:

格式化金额为字符串,自动添加货币符号,使用对应货币的默认小数位和舍入模式,简化调用。

java 复制代码
/**
 * DecimalFormat 线程本地缓存
 * 作用:避免重复创建 DecimalFormat 实例,提升性能;确保线程安全
 */
private static final ThreadLocal<DecimalFormatHelper> DECIMAL_FORMAT_CACHE =
        ThreadLocal.withInitial(DecimalFormatHelper::new);

/**
 * 法币类型枚举
 * 说明:
 * - 小数位数:不同货币可能有不同的小数位要求
 * - 货币符号:可用于格式化输出
 * - 舍入模式:不同货币可能有不同的舍入需求,默认使用 HALF_UP
 */
public enum Currency {
    // 人民币, 2位小数 , 默认舍入模式 HALF_UP
    CNY(2, "¥", RoundingMode.HALF_UP),
    // 美元, 2位小数, 默认舍入模式 HALF_UP
    USD(2, "$", RoundingMode.HALF_UP),
    // 欧元, 2位小数, 默认舍入模式 HALF_UP
    EUR(2, "€", RoundingMode.HALF_UP),
    // 日元, 0位小数(不使用小数部分), 默认舍入模式 HALF_UP
    JPY(0, "¥", RoundingMode.HALF_UP);

    private final int scale;
    private final String symbol;
    private final RoundingMode rounding;

    Currency(int scale, String symbol, RoundingMode rounding) {
        this.scale = scale;
        this.symbol = symbol;
        this.rounding = rounding;
    }
    public int getScale() {
        return scale;
    }

    public String getSymbol() {
        return symbol;
    }

    public RoundingMode getRounding() {
        return rounding;
    }
}

public static String formatMoney(BigDecimal amount, Currency currency) {
    Objects.requireNonNull(amount, "金额不能为空");
    Objects.requireNonNull(currency, "货币类型不能为空");
    // 对金额进行舍入,保留 currency.getScale() 位小数
    // 并使用 currency.getRounding() 来处理四舍五入
    BigDecimal rounded = roundMoney(amount, currency);
    // 从 ThreadLocal 获取 DecimalFormatHelper 实例,避免重复创建 DecimalFormat 对象,提升性能
    DecimalFormatHelper helper = DECIMAL_FORMAT_CACHE.get();

    try {
        // 配置 DecimalFormat,根据货币的要求设置小数位数、舍入模式和分组使用,确保格式化输出符合预期
        DecimalFormat df = helper.getFormat();
        // 强制设置小数位数,确保与货币规则一致(最小/最大小数位相同)
        df.setMinimumFractionDigits(currency.getScale());
        df.setMaximumFractionDigits(currency.getScale());
        // 设置舍入模式,与货币定义保持统一
        df.setRoundingMode(currency.getRounding());
        // 开启千分位分组,符合财务金额展示习惯
        df.setGroupingUsed(true);
        // 返回格式化后的字符串,包含货币符号和金额,确保输出符合预期的格式
        return currency.getSymbol() + df.format(rounded);
    } finally {
        DECIMAL_FORMAT_CACHE.remove();  // ✅ 关键:移除 ThreadLocal,避免内存泄漏
    }
}

2、格式化金额为字符串(不含货币符号)

场景说明:

格式化金额为字符串,不添加货币符号,使用对应货币的默认小数位和舍入模式,简化调用。

例如:formatMoneyPlain(123.456, Currency.USD) 会返回 "123.46"

formatMoneyPlain(123.456, Currency.JPY) 会返回 "123"

formatMoneyPlain(123.456, Currency.CNY) 会返回 "123.46"

java 复制代码
/**
* DecimalFormat 线程本地缓存
* 作用:避免重复创建 DecimalFormat 实例,提升性能;确保线程安全
*/
private static final ThreadLocal<DecimalFormatHelper> DECIMAL_FORMAT_CACHE =
        ThreadLocal.withInitial(DecimalFormatHelper::new);

/**
* 法币类型枚举
* 说明:
* - 小数位数:不同货币可能有不同的小数位要求
* - 货币符号:可用于格式化输出
* - 舍入模式:不同货币可能有不同的舍入需求,默认使用 HALF_UP
*/
public enum Currency {
    // 人民币, 2位小数 , 默认舍入模式 HALF_UP
    CNY(2, "¥", RoundingMode.HALF_UP),
    // 美元, 2位小数, 默认舍入模式 HALF_UP
    USD(2, "$", RoundingMode.HALF_UP),
    // 欧元, 2位小数, 默认舍入模式 HALF_UP
    EUR(2, "€", RoundingMode.HALF_UP),
    // 日元, 0位小数(不使用小数部分), 默认舍入模式 HALF_UP
    JPY(0, "¥", RoundingMode.HALF_UP);

    private final int scale;
    private final String symbol;
    private final RoundingMode rounding;

    Currency(int scale, String symbol, RoundingMode rounding) {
        this.scale = scale;
        this.symbol = symbol;
        this.rounding = rounding;
    }
    public int getScale() {
        return scale;
    }

    public String getSymbol() {
        return symbol;
    }
    public RoundingMode getRounding() {
        return rounding;
    }
}


/**
 *
 * @param amount 金额
 * @param currency 货币类型
 * @return 格式化后的字符串
 */
public static String formatMoneyPlain(BigDecimal amount, Currency currency) {
    Objects.requireNonNull(amount, "金额不能为空");
    Objects.requireNonNull(currency, "货币类型不能为空");

    BigDecimal rounded = roundMoney(amount, currency);
    DecimalFormatHelper helper = DECIMAL_FORMAT_CACHE.get();

    try {
        DecimalFormat df = helper.getFormat();
        df.setMinimumFractionDigits(currency.getScale());
        df.setMaximumFractionDigits(currency.getScale());
        df.setRoundingMode(currency.getRounding());
        df.setGroupingUsed(true);
        return df.format(rounded);
    } finally {
        DECIMAL_FORMAT_CACHE.remove();  // ✅ 关键:移除 ThreadLocal
    }
}
5.8. 计算百分比

场景说明:

计算百分比,自动处理分母为零的情况,避免调用方需要额外的 null 检查和异常处理。

例如:计算分子占分母的百分比,或者计算一个金额占另一个金额的百分比等场景。

java 复制代码
public static boolean eqZero(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    // 使用 compareTo 而不是 equals 来比较 BigDecimal 是否等于 0,避免 scale 不同导致的比较失败
    return amount.compareTo(BigDecimal.ZERO) == 0;
}

/**
 * 计算百分比
 * 实现说明:
 * return ratio.multiply(BigDecimal.valueOf(100)).setScale(scale, DEFAULT_ROUND)
 * 表示计算百分比,先计算分子与分母的比值,保留 scale + 2 位小数以避免过早舍入导致的精度问题
 * 然后乘以 100 得到百分比值,最后再舍入到指定的 scale 位小数,使用默认的舍入模式
 * return BigDecimal.ZERO 表示如果分母为零,直接返回 0%,避免抛出异常,简化调用方的错误处理逻辑
 *
 * 例子:
 * percent(123.456, 2, 2) 会返回 "62.50%"
 * percent(123.456, 0, 2) 会返回 "0.00%",避免分母为零导致的异常
 *
 * @param numerator 分子
 * @param denominator 分母
 * @param scale 结果小数位
 * @return 百分比值
 */
public static BigDecimal percent(
        BigDecimal numerator,
        BigDecimal denominator,
        int scale) {

    Objects.requireNonNull(numerator, "分子不能为空");
    Objects.requireNonNull(denominator, "分母不能为空");

    if (eqZero(denominator)) {
        return BigDecimal.ZERO;
    }
    // 计算百分比,先计算分子与分母的比值,保留 scale + 2 位小数以避免过早舍入导致的精度问题
    // 然后乘以 100 得到百分比值,最后再舍入到指定的 scale 位小数,使用默认的舍入模式
    BigDecimal ratio = divide(numerator, denominator, scale + 2, DEFAULT_ROUND);
    return ratio.multiply(BigDecimal.valueOf(100)).setScale(scale, DEFAULT_ROUND);
}
5.9. 判断金额是否有效

验证规则:

  1. 金额不能为 null
  2. 金额必须为正数或零
  3. 金额的小数位数不能超过货币规定的小数位数
java 复制代码
/**
 * 法币类型枚举
 * 说明:
 * - 小数位数:不同货币可能有不同的小数位要求
 * - 货币符号:可用于格式化输出
 * - 舍入模式:不同货币可能有不同的舍入需求,默认使用 HALF_UP
 */
public enum Currency {
    // 人民币, 2位小数 , 默认舍入模式 HALF_UP
    CNY(2, "¥", RoundingMode.HALF_UP),
    // 美元, 2位小数, 默认舍入模式 HALF_UP
    USD(2, "$", RoundingMode.HALF_UP),
    // 欧元, 2位小数, 默认舍入模式 HALF_UP
    EUR(2, "€", RoundingMode.HALF_UP),
    // 日元, 0位小数(不使用小数部分), 默认舍入模式 HALF_UP
    JPY(0, "¥", RoundingMode.HALF_UP);




    private final int scale;
    private final String symbol;
    private final RoundingMode rounding;




    Currency(int scale, String symbol, RoundingMode rounding) {
        this.scale = scale;
        this.symbol = symbol;
        this.rounding = rounding;
    }

    public int getScale() {
        return scale;
    }

    public String getSymbol() {
        return symbol;
    }

    public RoundingMode getRounding() {
        return rounding;
    }
}


/**
 * 判断金额是否为负数(小于 0)
 * 场景说明:
 * 判断金额是否为负数,用于验证金额输入是否合法
 * 例如:检查是否为退款、负调整等负数金额场景
 * 
 * @param amount 金额
 * @return 如果 amount < 0 则返回 true,否则返回 false
 */
public static boolean isNegative(BigDecimal amount) {
    Objects.requireNonNull(amount, "金额不能为空");
    return ltZero(amount);
}


/**
 * 判断金额是否有效(符合法币规则)
 * 场景说明:
 * 判断金额是否有效,包括检查小数位数是否符合货币规则
 * 例如:检查 USD 金额是否只有 2 位小数、JPY 是否有小数部分等
 * 
 * 
 * @param amount 金额
 * @param currency 货币类型
 * @return 如果金额有效则返回 true,否则返回 false
 */
public static boolean isValidCurrency(BigDecimal amount, Currency currency) {
    if (amount == null) {
        return false;
    }
    if (currency == null) {
        return false;
    }
    
    // 检查金额是否为非负数
    if (isNegative(amount)) {
        return false;
    }
    
    // 检查金额的小数位数是否符合货币规则
    // 获取金额的 scale(小数位数)
    int amountScale = amount.scale();
    int currencyScale = currency.getScale();
    
    // 小数位数不能超过货币规定的小数位数
    // 例如:USD 规定 2 位小数,金额不能有 3 位或以上小数
    if (amountScale > currencyScale) {
        return false;
    }
    
    return true;
}
相关推荐
我登哥MVP1 小时前
SpringCloud Alibaba 核心组件解析:服务注册与发现(Nacos)
java·spring boot·后端·spring·spring cloud·java-ee·maven
2601_960463832 小时前
FPG平台:围绕执行效率与合规意识的框架评估
金融
兰令水2 小时前
leecodecode【单调栈】【2026.6.12打卡-java版本】
java·开发语言·算法
云烟成雨TD2 小时前
Agent Scope Java 2.x 系列【8】工具调用
java·人工智能·agent
他们叫我技术总监2 小时前
Kettle(PDI)连接TDengine数据库实战:一个有趣的小现象
大数据·数据库·tdengine
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第112题】【并发篇】第12题:AQS 中节点的入队时机有哪些?
java·开发语言·面试
摇滚侠2 小时前
SpringMVC 入门到实战 处理静态资源的过程 64
java·后端·spring·maven·intellij-idea
影寂ldy2 小时前
C# 泛型委托
java·算法·c#
SilentSamsara2 小时前
RAG 系统入门:LangChain/LlamaIndex + Chroma 向量数据库的检索增强实战
数据库·人工智能·python·青少年编程·langchain