贷后催收专用分案算法

最优分案算法:

在开发中,有这么一种业务场景,就是需要根据一定的比例,按照数量与金额都按照这个比例进行分配,要求数量与金额都能达到最优的情况。如果只按照数量或者金额分配是比较好计算的,但是两者都需要兼顾到,这是一种比较复杂的算法,我现在将我的算法demo贴出来,供同学们一起学习一下。


可以直接将代码拷贝到本地,main方法直接运行

package cn.com.smart.eq.test;

import java.awt.*;

public class CaseAssignTool {
    public CaseAssignTool() {
    }

    public static void main(String[] args) {
        CaseFrame frame = new CaseFrame();
        frame.setTitle("手工分案-V2.8");
        frame.setDefaultCloseOperation(3);
        frame.setLocationRelativeTo((Component)null);
        frame.setVisible(true);
        frame.setResizable(false);
    }
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package cn.com.smart.eq.test;

import com.zpp.dto.AssignDto;
import com.zpp.dto.CaseDto;
import java.awt.Font;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

class CaseFrame extends JFrame {
    private static final long serialVersionUID = -4289784953416095500L;
    private Font font = new Font("微软雅黑", 0, 18);
    private int hd = 30;
    private JTextField fileText;
    private JTextField percentText;
    private JButton assign;
    private JButton select;
    private JButton clean;
    private JScrollPane scroll;
    private JTextArea area;
    private JRadioButton autoOpen;
    private JComboBox<Integer> minBox;
    String filePath = "/Users/candy/Desktop/aa.xlsx";
    String percent = "1,2,3,4";
    Integer[] arr = new Integer[]{200, 300, 400, 500, 1000};

    public CaseFrame() {
        this.setSize(645, 430);
        this.getContentPane().setLayout((LayoutManager)null);
        int yy = 10;
        this.add(this.setLabel(yy, 20, 110, "分案文件"), (Object)null);
        this.add(this.setFileText(yy, 105, 410, this.filePath), (Object)null);
        this.add(this.setSelectButton(yy, 530, 90, "选择", new SelectListener((SelectListener)null)), (Object)null);
        yy = 45;
        this.add(this.setLabel(yy, 20, 110, "对象占比"), (Object)null);
        this.add(this.setPercentText(yy, 105, 180, this.percent), (Object)null);
        this.add(this.setMinBox(yy, 295, 75, this.arr), (Object)null);
        this.add(this.setCleanButton(yy, 380, 71, "清空", new CleanListener((CleanListener)null)), (Object)null);
        this.add(this.setOpenRadio(yy, 455, 71, "打开", false), (Object)null);
        this.add(this.setAssignButton(yy, 530, 90, "分配", new AssignListener((AssignListener)null)), (Object)null);
        this.add(this.setArea(20, 80, 600, 300, true), (Object)null);
        this.add(this.setScroll(20, 80, 600, 300, this.area), (Object)null);
    }

    private JLabel setLabel(int y, int x, int w, String text) {
        JLabel label = new JLabel(text);
        label.setBounds(x, y, w, this.hd);
        label.setFont(this.font);
        return label;
    }

    private JTextField setFileText(int y, int x, int w, String text) {
        if (this.fileText == null) {
            this.fileText = new JTextField(text);
        }

        this.fileText.setBounds(x, y, w, this.hd);
        this.fileText.setFont(this.font);
        return this.fileText;
    }

    private JTextField setPercentText(int y, int x, int w, String text) {
        if (this.percentText == null) {
            this.percentText = new JTextField(text);
        }

        this.percentText.setBounds(x, y, w, this.hd);
        this.percentText.setFont(this.font);
        return this.percentText;
    }

    private JComboBox<Integer> setMinBox(int y, int x, int w, Integer[] arr) {
        if (this.minBox == null) {
            this.minBox = new JComboBox();
        }

        this.minBox.setBounds(x, y, w, this.hd);
        this.minBox.setFont(this.font);
        Integer[] var8 = arr;
        int var7 = arr.length;

        for(int var6 = 0; var6 < var7; ++var6) {
            Integer item = var8[var6];
            this.minBox.addItem(item);
        }

        return this.minBox;
    }

    private JRadioButton setOpenRadio(int y, int x, int w, String text, boolean select) {
        if (this.autoOpen == null) {
            this.autoOpen = new JRadioButton(text);
        }

        this.autoOpen.setBounds(x, y, w, this.hd);
        this.autoOpen.setFont(this.font);
        this.autoOpen.setSelected(select);
        return this.autoOpen;
    }

    private JButton setSelectButton(int y, int x, int w, String text, SelectListener actionListener) {
        if (this.select == null) {
            this.select = new JButton(text);
        }

        this.select.setBounds(x, y, w, this.hd);
        this.select.setFont(this.font);
        this.select.addActionListener(actionListener);
        return this.select;
    }

    private JButton setCleanButton(int y, int x, int w, String text, CleanListener actionListener) {
        if (this.clean == null) {
            this.clean = new JButton(text);
        }

        this.clean.setBounds(x, y, w, this.hd);
        this.clean.setFont(this.font);
        this.clean.addActionListener(actionListener);
        return this.clean;
    }

    private JButton setAssignButton(int y, int x, int w, String text, AssignListener actionListener) {
        if (this.assign == null) {
            this.assign = new JButton(text);
        }

        this.assign.setBounds(x, y, w, this.hd);
        this.assign.setFont(this.font);
        this.assign.addActionListener(actionListener);
        return this.assign;
    }

    private JTextArea setArea(int x, int y, int w, int h, boolean scroll) {
        if (this.area == null) {
            this.area = new JTextArea();
        }

        this.area.setBounds(x, y, w, h);
        this.area.setAutoscrolls(scroll);
        this.area.setFont(this.font);
        return this.area;
    }

    private JScrollPane setScroll(int x, int y, int w, int h, JTextArea area) {
        if (this.scroll == null) {
            this.scroll = new JScrollPane();
        }

        this.scroll.setBounds(x, y, w, h);
        this.scroll.setViewportView(area);
        return this.scroll;
    }

    private class AssignListener implements ActionListener {
        private AssignListener(AssignListener assignListener) {
        }

        public void actionPerformed(ActionEvent e) {
            String perStr = CaseFrame.this.percentText.getText();
            if (!this.regex(perStr.trim(), "\\d+(\\.\\d+)?(\\s*,\\s*\\d+(\\.\\d+)?)*")) {
                this.append("【分配对象】值有误");
            } else {
                String path = CaseFrame.this.fileText.getText();
                if (path != null && !"".equals(path.trim())) {
                    File file = new File(path);
                    if (!file.exists()) {
                        this.append("【分案文件】不存在");
                    } else {
                        long fileSize = file.length();
                        this.append("文件大小=" + String.format("%.3f", (double)(fileSize / 1024L) / 1024.0) + "MB");
                        Workbook book = this.excel2book(file);
                        if (book == null) {
                            this.append("创建【Workbook】为空");
                        } else {
                            Sheet sheet = book.getSheetAt(0);
                            int rowNum = sheet.getLastRowNum();
                            this.append("总行数=" + (rowNum + 1));
                            List<String> headList = this.row2list(sheet.getRow(0));
                            List<String> mustHeads = Arrays.asList("案件号", "逾期金额");
                            Iterator var13 = mustHeads.iterator();

                            while(var13.hasNext()) {
                                String mustHead = (String)var13.next();
                                if (!headList.contains(mustHead)) {
                                    this.append("表头必须包含【" + mustHead + "】字段");
                                    return;
                                }
                            }

                            List<CaseDto> caseList = new ArrayList<>();
                            this.sheet2list(caseList, sheet, rowNum, headList);
                            if (caseList.isEmpty()) {
                                this.append("【生成case】为空");
                            } else {
                                int max = caseList.size();
                                Map<AssignDto, List<CaseDto>> result = this.assign(caseList, perStr, max);
                                Iterator var16 = result.entrySet().iterator();
                                while(var16.hasNext()) {
                                    Map.Entry<AssignDto, List<CaseDto>> entry = (Map.Entry)var16.next();
                                    ((AssignDto)entry.getKey()).setRealAmt(entry.getValue().stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
                                    ((AssignDto)entry.getKey()).setRealNum(((List)entry.getValue()).size());
                                }

                                List<AssignDto> dtos = (List)result.keySet().stream().sorted(Comparator.comparing(AssignDto::getOffset)).collect(Collectors.toList());
                                this.printList("实际结果", dtos, true);
                                this.data2excel(result, path);
                            }
                        }
                    }
                } else {
                    this.append("【分案文件】值为空");
                }
            }
        }

        private Workbook excel2book(File file) {
            InputStream fis = null;

            try {
                fis = new FileInputStream(file);
            } catch (Exception var15) {
                this.append("创建【InputStream】失败");
            }

            Workbook book = null;

            try {
                book = WorkbookFactory.create(fis);
            } catch (Exception var14) {
                this.append("创建【Workbook】失败");
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException var13) {
                        this.append("关闭【InputStream】失败");
                    }
                }

            }

            return book;
        }

        private void sheet2list(List<CaseDto> caseList, Sheet sheet, int rowNum, List<String> headList) {
            int size = headList.size();

            for(int i = 1; i <= rowNum; ++i) {
                Row row = sheet.getRow(i);
                if (row == null) {
                    this.append("【空行】第" + (i + 1) + "行");
                    return;
                }

                CaseDto dto = new CaseDto();

                for(int j = 0; j < size; ++j) {
                    Cell cell = row.getCell(j);
                    String cellVal = null;
                    String var12;
                    switch ((var12 = (String)headList.get(j)).hashCode()) {
                        case 26302985:
                            if (!var12.equals("案件号")) {
                                return;
                            }

                            cellVal = this.cell2string(cell, true);
                            if (StringUtils.isBlank(cellVal)) {
                                this.append("第" + (i + 1) + "行【" + (String)headList.get(j) + "】为空");
                                return;
                            }

                            dto.setCaseId(Long.valueOf(cellVal));
                            break;
                        case 1126628173:
                            if (var12.equals("逾期金额")) {
                                cellVal = this.cell2string(cell, true);
                                if (StringUtils.isBlank(cellVal)) {
                                    this.append("第" + (i + 1) + "行【" + (String)headList.get(j) + "】为空");
                                    return;
                                }

                                dto.setAmtBal(new BigDecimal(cellVal));
                                break;
                            }

                            return;
                        default:
                            return;
                    }
                }

                caseList.add(dto);
            }

        }

        private Map<AssignDto, List<CaseDto>> assign(List<CaseDto> caseList, String percentStr, int max) {
            BigDecimal totalAmt = (BigDecimal)caseList.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add);
            List<AssignDto> userList = this.buildAssignDto(percentStr, caseList.size(), totalAmt, max);
            this.printAssignDto(userList);
            long start = System.currentTimeMillis();

            this.append("\n<< 分案开始 >>");
            Map<AssignDto, List<CaseDto>> userMap = this.oneStep(caseList, userList, totalAmt.multiply(new BigDecimal("0.0001")), max / 2);
            Map<AssignDto, List<CaseDto>> map = this.fixResult(userMap);
            long end = System.currentTimeMillis();
            this.append("\n<< 分案完成 >> 耗时:" + (double)(end - start) / 1000.0 + "s");
            return map;
        }

        private void printAssignDto(List<AssignDto> userList) {
            Map<String, List<AssignDto>> keyUser = new HashMap();

            AssignDto curr;
            String userId;
            for(Iterator var4 = userList.iterator(); var4.hasNext(); ((List)keyUser.get(userId)).add(curr)) {
                curr = (AssignDto)var4.next();
                userId = curr.getUserId().split("_", 2)[0];
                if (!keyUser.containsKey(userId)) {
                    keyUser.put(userId, new ArrayList());
                }
            }

            List<AssignDto> result = new ArrayList();
            Iterator var11 = keyUser.entrySet().iterator();

            while(var11.hasNext()) {
                Map.Entry<String, List<AssignDto>> entry = (Map.Entry)var11.next();
                AssignDto dto = new AssignDto((String)entry.getKey(), BigDecimal.ZERO);
                Iterator var8 = ((List)entry.getValue()).iterator();

                while(var8.hasNext()) {
                    AssignDto currx = (AssignDto)var8.next();
                    dto.setPercent(currx.getPercent());
                    dto.setAssignNum(dto.getAssignNum() + currx.getAssignNum());
                    dto.setAssignAmt(dto.getAssignAmt().add(currx.getAssignAmt()));
                    dto.setRealNum(dto.getRealNum() + currx.getRealNum());
                    dto.setRealAmt(dto.getRealAmt().add(currx.getRealAmt()));
                }

                result.add(dto);
            }

            this.printList("分配汇总", result, true);
        }

        private List<AssignDto> buildAssignDto(String percentStr, int caseSize, BigDecimal totalAmt, int max) {
            BigDecimal caseNum = BigDecimal.valueOf((long)caseSize);
            BigDecimal avgAmt = totalAmt.divide(caseNum, 2, 4);
            this.append("案件总数=" + caseSize + ",案件总金额=" + totalAmt + ",平均金额=" + avgAmt);
            BigDecimal totalPercent = BigDecimal.ZERO;
            List<BigDecimal> percents = new ArrayList();
            String[] str = percentStr.trim().split("\\s*,\\s*");
            int len;
            int size;
            if (str.length == 1) {
                len = (int)Double.parseDouble(str[0]);

                for(size = 1; size <= len; ++size) {
                    percents.add(BigDecimal.ONE);
                }

                totalPercent = BigDecimal.valueOf((long)len);
            } else {
                for(len = 0; len < str.length; ++len) {
                    BigDecimal curr = new BigDecimal(str[len]);
                    if (curr.compareTo(BigDecimal.ZERO) > 0) {
                        percents.add(curr);
                        totalPercent = totalPercent.add(curr);
                    }
                }
            }

            Collections.sort(percents);
            List<AssignDto> dtos = new ArrayList();
            size = percents.size();
            BigDecimal passAmt = BigDecimal.ZERO;
            int passNum = 0;

            int left;
            for(int i = 0; i < size - 1; ++i) {
                String userIdx = "U" + (i + 1) + "_";
                BigDecimal px = (BigDecimal)percents.get(i);
                int assignNumx = caseNum.multiply(px).divide(totalPercent, 2, 1).intValue();
                BigDecimal assignAmtx = totalAmt.multiply(px).divide(totalPercent, 2, 4);
                left = assignNumx / max;
                int leftx = assignNumx % max;
                BigDecimal passx;
                int j;
                BigDecimal amt;
                AssignDto d;
                AssignDto dx;
                if (leftx > 0) {
                    passx = BigDecimal.ZERO;

                    for(j = 0; j < left; ++j) {
                        amt = assignAmtx.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNumx), 2, 4);
                        d = new AssignDto(userIdx + j, px);
                        d.setAssignNum(max);
                        d.setAssignAmt(amt);
                        dtos.add(d);
                        passx = passx.add(amt);
                    }

                    dx = new AssignDto(userIdx + left, px);
                    dx.setAssignNum(leftx);
                    dx.setAssignAmt(assignAmtx.subtract(passx));
                    dtos.add(dx);
                } else {
                    passx = BigDecimal.ZERO;

                    for(j = 0; j < left - 1; ++j) {
                        amt = assignAmtx.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNumx), 2, 4);
                        d = new AssignDto(userIdx + j, px);
                        d.setAssignNum(max);
                        d.setAssignAmt(amt);
                        dtos.add(d);
                        passx = passx.add(amt);
                    }

                    dx = new AssignDto(userIdx + (left - 1), px);
                    dx.setAssignNum(leftx);
                    dx.setAssignAmt(assignAmtx.subtract(passx));
                    dtos.add(dx);
                }

                passAmt = passAmt.add(assignAmtx);
                passNum += assignNumx;
            }

            if (passNum < caseSize) {
                String userId = "U" + size + "_";
                BigDecimal p = (BigDecimal)percents.get(size - 1);
                int assignNum = caseSize - passNum;
                BigDecimal assignAmt = totalAmt.subtract(passAmt);
                int time = assignNum / max;
                left = assignNum % max;
                BigDecimal pass;
                int jx;
                AssignDto dxx;
                AssignDto dxxx;
                BigDecimal amtx;
                if (left > 0) {
                    pass = BigDecimal.ZERO;

                    for(jx = 0; jx < time; ++jx) {
                        amtx = assignAmt.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNum), 2, 4);
                        dxxx = new AssignDto(userId + jx, p);
                        dxxx.setAssignNum(max);
                        dxxx.setAssignAmt(amtx);
                        dtos.add(dxxx);
                        pass = pass.add(amtx);
                    }

                    dxx = new AssignDto(userId + time, p);
                    dxx.setAssignNum(left);
                    dxx.setAssignAmt(assignAmt.subtract(pass));
                    dtos.add(dxx);
                } else {
                    pass = BigDecimal.ZERO;

                    for(jx = 0; jx < time - 1; ++jx) {
                        amtx = assignAmt.multiply(BigDecimal.valueOf((long)max)).divide(BigDecimal.valueOf((long)assignNum), 2, 4);
                        dxxx = new AssignDto(userId + jx, p);
                        dxxx.setAssignNum(max);
                        dxxx.setAssignAmt(amtx);
                        dtos.add(dxxx);
                        pass = pass.add(amtx);
                    }

                    dxx = new AssignDto(userId + (time - 1), p);
                    dxx.setAssignNum(left);
                    dxx.setAssignAmt(assignAmt.subtract(pass));
                    dtos.add(dxx);
                }
            }

            List<AssignDto> dtosx = (List)dtos.stream().filter((u) -> {
                return u.getAssignNum() > 0;
            }).collect(Collectors.toList());
            dtosx.sort(Comparator.comparing(AssignDto::getAssignNum));
            return dtosx;
        }

        private Map<AssignDto, List<CaseDto>> fixResult(Map<AssignDto, List<CaseDto>> map) {
            Map<String, List<AssignDto>> keyUser = new HashMap();
            Map<String, List<CaseDto>> keyCase = new HashMap();

            Map.Entry entryx;
            String userId;
            for(Iterator var5 = map.entrySet().iterator(); var5.hasNext(); ((List)keyCase.get(userId)).addAll((Collection)entryx.getValue())) {
                entryx = (Map.Entry)var5.next();
                AssignDto curr = (AssignDto)entryx.getKey();
                userId = curr.getUserId().split("_", 2)[0];
                if (!keyUser.containsKey(userId)) {
                    keyUser.put(userId, new ArrayList());
                }

                ((List)keyUser.get(userId)).add((AssignDto)entryx.getKey());
                if (!keyCase.containsKey(userId)) {
                    keyCase.put(userId, new ArrayList());
                }
            }

            Map<AssignDto, List<CaseDto>> result = new HashMap();
            Iterator var12 = keyUser.entrySet().iterator();

            while(var12.hasNext()) {
                Map.Entry<String, List<AssignDto>> entry = (Map.Entry)var12.next();
                AssignDto dto = new AssignDto((String)entry.getKey(), BigDecimal.ZERO);
                Iterator var9 = ((List)entry.getValue()).iterator();

                while(var9.hasNext()) {
                    AssignDto currx = (AssignDto)var9.next();
                    dto.setPercent(currx.getPercent());
                    dto.setAssignNum(dto.getAssignNum() + currx.getAssignNum());
                    dto.setAssignAmt(dto.getAssignAmt().add(currx.getAssignAmt()));
                    dto.setRealNum(dto.getRealNum() + currx.getRealNum());
                    dto.setRealAmt(dto.getRealAmt().add(currx.getRealAmt()));
                }

                result.put(dto, (List)keyCase.get(entry.getKey()));
            }

            return result;
        }

        private Map<AssignDto, List<CaseDto>> oneStep(List<CaseDto> caseList, List<AssignDto> userList, BigDecimal maxOffset, int maxTimes) {
            this.append("\n最大偏差仅=" + maxOffset + ",最大微调次数=" + maxTimes);
            Map<AssignDto, List<CaseDto>> map = new HashMap<>();
            List<CaseDto> left = caseList;
            int usize = userList.size();

            for(int x = 0; x < usize - 1; ++x) {
                int size = ((List<?>)left).size();
                int num = ((AssignDto)userList.get(x)).getAssignNum();
                int mod = size / num;
                List<CaseDto> curr = new ArrayList<>();
                List<CaseDto> temp = new ArrayList<>();

                for(int j = 0; j < size; ++j) {
                    if (j % mod == (j / mod % 2 == 0 ? 0 : mod - 1) && curr.size() < num) {
                        curr.add((CaseDto)((List<?>)left).get(j));
                    } else {
                        temp.add((CaseDto)((List<?>)left).get(j));
                    }
                }

                ((AssignDto)userList.get(x)).setRealAmt((BigDecimal)curr.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
                BigDecimal offset = ((AssignDto)userList.get(x)).getOffset();
                int currSize = curr.size();
                int leftSize = temp.size();
                int times = 1;

                for(String flag = ((AssignDto)userList.get(x)).getUserId() + ":0"; offset.abs().compareTo(maxOffset) > 0 && times < maxTimes; ++times) {
                    BigDecimal lastSub = offset.abs();
                    String lastFlag = flag;
                    int[] idx = new int[]{currSize - 1, leftSize - 1};

                    BigDecimal currSub;
                    for(int k = 0; k < currSize; ++k) {
                        for(int m = 0; m < leftSize; ++m) {
                            currSub = ((CaseDto)temp.get(m)).getAmtBal().subtract(((CaseDto)curr.get(k)).getAmtBal()).add(offset).abs();
                            if (currSub.compareTo(lastSub) < 0) {
                                idx[0] = k;
                                idx[1] = m;
                                lastSub = currSub;
                                lastFlag = ((AssignDto)userList.get(x)).getUserId() + ":" + k;
                            }
                        }
                    }

                    if (offset.abs().compareTo(lastSub) == 0 && flag.equals(lastFlag)) {
                        this.append((times == 1 ? "\n" : "") + "【" + ((AssignDto)userList.get(x)).getUserId() + "】第" + times + "次:已最优,跳出循环");
                        break;
                    }

                    this.append((times == 1 ? "\n" : "") + "【" + ((AssignDto)userList.get(x)).getUserId() + "】第" + times + "次:调前=" + offset + ",调后=" + lastSub + ",交换[ " + idx[0] + " <> " + idx[1] + " ]");
                    CaseDto c1 = (CaseDto)curr.get(idx[0]);
                    CaseDto c2 = (CaseDto)temp.get(idx[1]);
                    curr.remove(idx[0]);
                    temp.remove(idx[1]);
                    curr.add(c2);
                    temp.add(c1);
                    currSub = c2.getAmtBal().subtract(c1.getAmtBal());
                    ((AssignDto)userList.get(x)).setRealAmt(((AssignDto)userList.get(x)).getRealAmt().add(currSub));
                    offset = ((AssignDto)userList.get(x)).getOffset();
                }

                left = temp;
                ((AssignDto)userList.get(x)).setRealNum(curr.size());
                map.put((AssignDto)userList.get(x), curr);
            }

            ((AssignDto)userList.get(usize - 1)).setRealAmt(left.stream().map(CaseDto::getAmtBal).reduce(BigDecimal.ZERO, BigDecimal::add));
            ((AssignDto)userList.get(usize - 1)).setRealNum(((List)left).size());
            map.put((AssignDto)userList.get(usize - 1), left);
            return map;
        }

        private void data2excel(Map<AssignDto, List<CaseDto>> result, String path) {
            Workbook book = new SXSSFWorkbook(64);
            Sheet sheet = book.createSheet("结果");
            List<String> heads = Arrays.asList("案件号", "分配对象", "逾期金额");
            int rix = 0;
            int hsize = heads.size();
            Row row = sheet.createRow(rix++);

            for(int i = 0; i < hsize; ++i) {
                Cell cell = row.createCell(i);
                cell.setCellValue((String)heads.get(i));
            }

            Iterator var28 = result.entrySet().iterator();

            while(var28.hasNext()) {
                Map.Entry<AssignDto, List<CaseDto>> entry = (Map.Entry)var28.next();
                Iterator var12 = ((List)entry.getValue()).iterator();

                while(var12.hasNext()) {
                    CaseDto dto = (CaseDto)var12.next();
                    row = sheet.createRow(rix++);
                    dto.setUserId(((AssignDto)entry.getKey()).getUserId());

                    for(int ix = 0; ix < hsize; ++ix) {
                        Cell cellx = row.createCell(ix);
                        switch ((String)heads.get(ix)) {
                            case "案件号":
                                cellx.setCellValue((double)dto.getCaseId());
                                break;
                            case "分配对象":
                                cellx.setCellValue(dto.getUserId());
                                break;
                            case "逾期金额":
                                cellx.setCellValue(dto.getAmtBal().doubleValue());
                        }
                    }
                }
            }

            String uuid = UUID.randomUUID().toString().replace("-", "");

            String newPath;
            for(newPath = path.replace(".xls", "结果-" + uuid + ".xls"); (new File(newPath)).exists(); newPath = path.replace(".xls", "结果-" + uuid + ".xls")) {
                uuid = UUID.randomUUID().toString().replace("-", "");
            }

            FileOutputStream out = null;

            try {
                out = new FileOutputStream(newPath);
                book.write(out);
                out.flush();
                this.append("\n生成结果文件【" + newPath + "】");
            } catch (Exception var24) {
                this.append("\n生成结果文件【" + newPath + "】失败");
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException var22) {
                        this.append("关闭【FileOutputStream】失败");
                    }
                }

            }

            if (CaseFrame.this.autoOpen.isSelected()) {
                String[] cmd = new String[]{"explorer.exe", newPath};

                try {
                    Runtime.getRuntime().exec(cmd);
                } catch (Exception var23) {
                    this.append("\n打开文件失败【" + newPath + "】");
                }

                this.append("\n自动打开文件【" + newPath + "】");
            }

        }

        private String cell2string(Cell cell, boolean nullToBlock) {
            String value = null;
            switch (cell.getCellType()) {
                case 0:
                    if (DateUtil.isCellDateFormatted(cell)) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        value = sdf.format(cell.getDateCellValue());
                    } else {
                        DecimalFormat df = new DecimalFormat("#.##");
                        value = df.format(cell.getNumericCellValue());
                    }
                    break;
                case 1:
                    value = cell.getStringCellValue();
                    break;
                case 2:
                    value = cell.getCellFormula();
                case 3:
                case 5:
                default:
                    break;
                case 4:
                    value = String.valueOf(cell.getBooleanCellValue());
            }

            if (StringUtils.isNotBlank(value)) {
                value = value.trim().replaceAll("\\s+", "").replaceAll(",", ",");
            } else if (nullToBlock) {
                value = "";
            }

            return value;
        }

        private List<String> row2list(Row row) {
            List<String> heads = new ArrayList();
            if (row != null) {
                int cellNum = row.getLastCellNum();

                for(int i = 0; i < cellNum; ++i) {
                    Cell cell = row.getCell(i);
                    if (cell != null) {
                        String feild = cell.getStringCellValue();
                        if (StringUtils.isNotBlank(feild)) {
                            heads.add(feild.trim());
                        }
                    }
                }
            }

            return heads;
        }

        private boolean regex(String input, String regex) {
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(input);
            return m.matches();
        }

        private void append(String text) {
            System.out.println(text);
            CaseFrame.this.area.append(text + "\n");
            CaseFrame.this.area.paintImmediately(CaseFrame.this.area.getBounds());
        }

        private void printList(String head, Collection<?> list, boolean append) {
            System.out.println("\n------------------------------ " + head + " ------------------------------");
            if (append) {
                CaseFrame.this.area.append("\n------------------------------ " + head + " ------------------------------\n");
            }

            list.forEach((a) -> {
                System.out.println(a.toString());
                if (append) {
                    CaseFrame.this.area.append(a.toString() + "\n");
                }

            });
            if (append) {
                CaseFrame.this.area.paintImmediately(CaseFrame.this.area.getBounds());
            }

        }
    }

    private class CleanListener implements ActionListener {
        private CleanListener(CleanListener cleanListener) {
        }

        public void actionPerformed(ActionEvent e) {
            CaseFrame.this.autoOpen.setSelected(false);
            CaseFrame.this.area.setText("");
        }
    }

    private class SelectListener implements ActionListener {
        private SelectListener(SelectListener selectListener) {
        }

        public void actionPerformed(ActionEvent e) {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setCurrentDirectory(new File("."));
            fileChooser.setFileSelectionMode(2);
            fileChooser.setFileFilter(new FileNameExtensionFilter("Excel (*.xlsx, *.xls)", new String[]{"xlsx", "xls"}));
            int result = fileChooser.showOpenDialog(new JFrame());
            if (result == 0) {
                File file = fileChooser.getSelectedFile();
                CaseFrame.this.fileText.setText(file.getAbsolutePath());
            }

        }
    }
}

相关依赖
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
        
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.8.1</version>
    </dependency>
用到的实体bean
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.zpp.dto;

import java.math.BigDecimal;

public class AssignDto {
    private String userId;
    private BigDecimal percent;
    private int assignNum;
    private int realNum;
    private BigDecimal assignAmt;
    private BigDecimal realAmt;
    private BigDecimal offset;

    public AssignDto(String userId, BigDecimal percent) {
        this.userId = userId;
        this.percent = percent;
        this.assignNum = 0;
        this.realNum = 0;
        this.assignAmt = BigDecimal.ZERO;
        this.realAmt = BigDecimal.ZERO;
        this.offset = BigDecimal.ZERO;
    }

    public String toString() {
        return "用户=" + this.userId + ",  权重=" + this.percent + ",  应分数量=" + this.assignNum + ",  实际数量=" + this.realNum + ",  应分金额=" + this.assignAmt + ",  实际金额=" + this.realAmt + ",  偏差量=" + this.offset;
    }

    public String getUserId() {
        return this.userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public BigDecimal getPercent() {
        return this.percent;
    }

    public void setPercent(BigDecimal percent) {
        this.percent = percent;
    }

    public int getAssignNum() {
        return this.assignNum;
    }

    public void setAssignNum(int assignNum) {
        this.assignNum = assignNum;
        this.realNum = 0;
    }

    public int getRealNum() {
        return this.realNum;
    }

    public void setRealNum(int realNum) {
        this.realNum = realNum;
    }

    public BigDecimal getAssignAmt() {
        return this.assignAmt;
    }

    public void setAssignAmt(BigDecimal assignAmt) {
        this.assignAmt = assignAmt;
        this.offset = BigDecimal.ZERO;
    }

    public BigDecimal getRealAmt() {
        return this.realAmt;
    }

    public void setRealAmt(BigDecimal realAmt) {
        this.realAmt = realAmt;
        this.offset = this.realAmt.subtract(this.assignAmt);
    }

    public BigDecimal getOffset() {
        return this.offset;
    }

    public void setOffset(BigDecimal offset) {
        this.offset = offset;
    }
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.zpp.dto;

import java.math.BigDecimal;

public class CaseDto {
    private Long caseId;
    private BigDecimal amtBal;
    private String userId;

    public CaseDto() {
    }

    public String toString() {
        return this.caseId + "," + this.amtBal + "," + this.userId;
    }

    public Long getCaseId() {
        return this.caseId;
    }

    public void setCaseId(Long caseId) {
        this.caseId = caseId;
    }

    public BigDecimal getAmtBal() {
        return this.amtBal;
    }

    public void setAmtBal(BigDecimal amtBal) {
        this.amtBal = amtBal;
    }

    public String getUserId() {
        return this.userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值