import java.math.BigDecimal;import java.math.RoundingMode;import java.util.ArrayList;import java.util.List;/** * 红包均分 * * @author liyulin * @version 1.0 2017年3月31日 上午11:28:35 */public final class MoneyUtil { /** * 红包金额根据所占总金额比例均分 * * @param totalAmt 总金额(单位:分),为null时,会在内部计算其值 * @param subAmts 所有资金额(单位:分) * @param totalHbAmt 红包总金额(单位:分) * @return 返回所有均分的金额(单位:分) */ public static final ListgetSubMoney(BigDecimal totalAmt, List subAmts, BigDecimal totalHbAmt) { if (totalAmt == null) { totalAmt = BigDecimal.ZERO; for (BigDecimal subAmt : subAmts) { totalAmt = totalAmt.add(subAmt); } } /** 因为计算时,最后一个的值为总红包金额减去其余红包总额,如果最后的账单金额为0,会出现红包金额为负数的情况 */ int dealSize = getDealSubAmtMaxIndex(subAmts);// 从最后一个开始倒序,实付为大于0的索引 /** 最后实付金额(连续)为非0的处理 */ List subHbAmts = dealNonNegative(dealSize, totalAmt, subAmts, totalHbAmt); /** 最后实付金额(连续)为0的处理 */ for (int i = dealSize + 1; i < subAmts.size(); i++) { subHbAmts.add(BigDecimal.ZERO); } /** 分配的最后一个红包为负数的处理 */ dealLastNegative(dealSize, subHbAmts, subAmts); return subHbAmts; } /** * 非0实付处理 * @param dealSize * @param totalAmt * @param subAmts * @param totalHbAmt * @return */ public static final List dealNonNegative(int dealSize, BigDecimal totalAmt, List subAmts, BigDecimal totalHbAmt) { List subHbAmts = new ArrayList (); BigDecimal otherTotalAmt = BigDecimal.ZERO; for (int i = 0; i <= dealSize; i++) { BigDecimal subHbAmt = null; if (i < dealSize) { BigDecimal subAmt = subAmts.get(i); subHbAmt = div(subAmt.multiply(totalHbAmt), totalAmt); BigDecimal subUpHbAmt = subHbAmt.setScale(0, RoundingMode.UP); if (subUpHbAmt.compareTo(subAmt) < 0) { subHbAmt = subUpHbAmt; } else { subHbAmt = subAmt; } otherTotalAmt = otherTotalAmt.add(subHbAmt); } else {// 最后一个 subHbAmt = totalHbAmt.subtract(otherTotalAmt); } subHbAmts.add(subHbAmt); } return subHbAmts; } /** * 获取处理的最后一个子帐单的索引 * @param subAmts * @return */ public static final int getDealSubAmtMaxIndex(List subAmts){ int dealSize = 0;// 从最后一个开始倒叙,实付为大于0的索引 /** 因为计算时,最后一个的值为总红包金额减去其余红包总额,如果最后的账单金额为0,会出现红包金额为负数的情况 */ for (int i = subAmts.size() - 1; i >= 0; i--) { BigDecimal subAmtTmp = subAmts.get(i); if (subAmtTmp.compareTo(BigDecimal.ZERO) != 0) { dealSize = i; break; } } return dealSize; } /** * 分配的最后一个红包为负数的处理 * @param dealSize * @param subHbAmts * @param subAmts */ public static final void dealLastNegative(int dealSize, List subHbAmts, List subAmts){ if(subHbAmts.get(dealSize).compareTo(BigDecimal.ZERO) < 0){ long balanceAmt = Math.abs(subHbAmts.get(dealSize).longValue()); subHbAmts.set(dealSize, BigDecimal.ZERO); for (int i = 0; i < dealSize; i++) { long partBalanceAmt = subAmts.get(i).longValue() - subHbAmts.get(i).longValue(); if (partBalanceAmt > 0) { if (partBalanceAmt >= balanceAmt) { subHbAmts.set(i, subHbAmts.get(i).subtract(BigDecimal.valueOf(balanceAmt))); break; } else { subHbAmts.set(i, subHbAmts.get(i).subtract(BigDecimal.valueOf(partBalanceAmt))); balanceAmt -= partBalanceAmt; if (balanceAmt == 0) { break; } } } } } } public static final BigDecimal div(BigDecimal num1, BigDecimal num2) { if (num1 == null || num2 == null) { return null; } return num1.divide(num2, 4, RoundingMode.DOWN); } public static void main(String[] args) { List subAmts = new ArrayList (); subAmts.add(BigDecimal.valueOf(48)); subAmts.add(BigDecimal.valueOf(122)); subAmts.add(BigDecimal.valueOf(196)); subAmts.add(BigDecimal.valueOf(10)); BigDecimal totalHbAmt = BigDecimal.valueOf(8); List allSubHbAmts = getSubMoney(null, subAmts, totalHbAmt); System.err.println(allSubHbAmts); }}