項(xiàng)目背景:建行收到財(cái)政發(fā)來的公務(wù)卡墊款xml報(bào)文存庫,報(bào)文格式分主單和明細(xì),主單不包含收款賬號(hào),明細(xì)單包含收款賬號(hào),即一個(gè)主單包含多個(gè)明細(xì)(明細(xì)確定不超過500,但具體多少,未知)!建行公務(wù)卡支付需按照明細(xì)支付,支付完成以后,需按主單生成清算單到人行做清算,也是主單+明細(xì)的情況,但是明細(xì)單有一個(gè)要求,不能超過500,超過500必須分包,而且必須保證一個(gè)主單的明細(xì)單必須在一個(gè)清算單中,不能存在一個(gè)主單對應(yīng)的明細(xì)單在兩個(gè)清算單中,而且必須保證清算單最少(不能10個(gè)公務(wù)卡,生成10張清算單)。

比如說主單A包含450條明細(xì)單,主單B包含300條明細(xì)單,主單C包含200條明細(xì)單,那么這種情況就只能生成3張清算單,如果主單D包含10條明細(xì)單,那么也只能生成3張清算單,雖然人行清算也是按照明細(xì)單做清算,但是為了三方對賬方便(主要還是財(cái)政),建行規(guī)則必須按照這種業(yè)務(wù)邏輯生成!
所以依據(jù)草稿(解決思路),理了一下業(yè)務(wù)邏輯:
1、取出Map<明細(xì)條數(shù),公務(wù)卡主單憑證號(hào)>
2、求Map明細(xì)條數(shù)的Sum
3、明細(xì)合計(jì)<499,則生成一個(gè)清算單,>499考慮遞歸,最終合計(jì)小于499為出口
模擬業(yè)務(wù)邏輯,代碼如下:
package xf;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class Person {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("79", "主單憑證號(hào)1"); // 1111
map.put("68", "主單憑證號(hào)2");
map.put("57", "主單憑證號(hào)3");
map.put("46", "主單憑證號(hào)4");
map.put("35", "主單憑證號(hào)5");
map.put("24", "主單憑證號(hào)6");
map.put("12", "主單憑證號(hào)7"); // 1111
map.put("1", "主單憑證號(hào)8"); // 1111
int count = SumList(map);
System.out.println("合計(jì)條數(shù)========" + count);
if (count < 100) {
System.out.println("就一筆清算單");
}
if (count > 100) {
System.out.println("清算明細(xì)單超過100======================================");
List<String> strArr = new ArrayList<String>();
strArr = returnVoucher(map); //第一次取出不超過100的主單憑證號(hào) AA
Map<String, String> remMap = new HashMap<String, String>();
remMap = returnRemoveMap(map, strArr); //第一次剔除AA
// 統(tǒng)計(jì)remMap明細(xì)條數(shù)
int sum = SumList(remMap);
boolean turn = true;
int n = 0;
int m = 0;
while (turn) {
if (sum < 100) {
// 直接生成最后一筆清算
System.err.println("我是最后一筆清算 我是出口 遞歸函數(shù)出口!");
strArr = returnVoucher(remMap); //剩下的
for (String str : strArr) {
System.err.println("最后剩下的憑證號(hào)==" + str);
}
turn = false;
break; // 出口
}
if (sum > 100) {
// 循環(huán)
n++;
m++;
System.err.println("生成第" + n + "筆清算!"); //此時(shí)的strArr剛好是第一次取出來的
remMap = returnRemoveMap(remMap, strArr); // 在剔除
System.out.println("第" + m + "次剔除!");
sum = SumList(remMap); // 判斷條數(shù)
System.out.println("統(tǒng)計(jì)明細(xì)條數(shù)===" + sum);
strArr = returnVoucher(remMap);
}
}
}
}
// 取出明細(xì)合計(jì)小于499的任意主單
public static List<String> returnVoucher(Map<String, String> map) {
List<String> strArr = new ArrayList<String>();
int sum = 0;
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
sum = sum + Integer.valueOf(entry.getKey()); // key是明細(xì)條數(shù)
if (sum < 100) {
strArr.add(entry.getValue());
// System.out.println("key= " + entry.getKey() + " and value= "
// + entry.getValue());
} else {
break;
}
}
return strArr;
}
// 剔除list 返回剩余Map
public static Map<String, String> returnRemoveMap(Map<String, String> map, List<String> listStr) {
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
for (String str : listStr) {
if (str.equals(entry.getValue())) {
// map.remove(entry.getKey()); //map移除元素必須用迭代器
it.remove();
}
}
}
return map;
}
//統(tǒng)計(jì)明細(xì)條數(shù)的sum
public static Integer SumList(Map<String, String> remMap) {
int sum = 0;
Iterator<Map.Entry<String, String>> it = remMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
sum = sum + Integer.valueOf(entry.getKey()); // key是明細(xì)條數(shù)
}
return sum;
}
}

main函數(shù)匯總的map,模擬數(shù)據(jù)庫中取出的Map,該業(yè)務(wù)邏輯需要注意的是,并非合計(jì)數(shù)除以500的結(jié)果+1就是最少清算單條數(shù),這個(gè)就是該業(yè)務(wù)最大難點(diǎn),比方說:
主單A包含450條明細(xì)單
主單B包含300條明細(xì)單
主單C包含200條明細(xì)單
主單D包含100條明細(xì)單
主單E包含350條明細(xì)單
雖然明細(xì)合計(jì)為1400,但是必須生成4張清算單,這是必須要注意到的地方!