List集合合併解決方案(兩天的成果)

需求不再贅述了,下面註釋有

package com.qdfae.jdk.collections;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.qdfae.jdk.domain.BizplanRepay;

/**
 * List集合合併
 * 
 * 需求:
 * 一個金融產品具有多個認購金額,不同的認購金額區間對應不同的年化收益率
 * 例如:
 * 認購金額       年化收益率
 * 50000           1.00%
 * 100000         3.00%
 * 200000         5.00%
 * 那麼現在的需求是投資者在投資認購者最低的認購金額就是50000起,
 * 認購金額在50000到99999之間那麼年化收益率爲1.00%
 * 認購金額在100000到199999之間那麼年化收益率爲3.00%
 * 認購金額在200000及以上的,那麼年化收益率爲5.00%
 * 
 * 投資者在投資認購後,系統經過確權後
 * 每個投資者訂單的確權金額也經過上述認購金額和年化收益率的計算
 * 1、如果出現一個投資者持有超過一筆訂單的情況,那麼確權金額就是所有訂單確權金額的總和
 *      那麼計算年化收益的年化收益率爲確權金額所在區間進行計算
 * 2、如果出現一個投資者確權金額小於最低的認購金額,那麼該投資者的確權金額對應的
 *      年化收益的年化收益率爲最低的年化收益率
 *      
 *  由於系統生成還款計劃(包含計息本金、本金、利息)是按照固定的年化收益率去計算的
 *  那麼對於多個年化收益率的金融產品不再適用,於是經過系統確權之後,
 *  按照不同的年化收益率計算對應的每個投資者確權金額的總和
 *  然後根據不同的年化收益率得出不同的確權本金,使用這兩個參數生成對應的還款計劃
 *  那麼就有合併還款計劃的需求,這就是問題
 *  
 *  經過分析得出可以得出這樣兩個方案:
 *  1、緩存不同年化收益率的還款計劃方案一
 *       使用Map集合:key爲年化收益率,
 *                               value爲年化收益率對應的還款計劃
 *  2、緩存不同年化收益率的還款計劃方案二
 *       使用List集合:元素爲不同年化收益率的還款計劃
 *  3、需要明確一點,還款計劃策略根據不同的還款方式生成的還款計劃是一個List集合
 *        詳見下面初始化數據方法
 *
 * @author hongwei.lian
 * @date 2018年5月19日 下午2:15:58
 */
public class MergeListTest {
	
	/**
	 * 年化收益率爲5%還款計劃
	 */
	private List<BizplanRepay> bizplanRepayList1;
	
	/**
	 * 緩存年化收益率爲10%還款計劃
	 */
	private List<BizplanRepay> bizplanRepayList2;
	
	/**
	 * 緩存年化收益率爲15%還款計劃
	 */
	private List<BizplanRepay> bizplanRepayList3;
	
	/**
	 * 緩存不同年化收益率的還款計劃方案一
	 * 使用Map集合:key爲年化收益率,value爲年化收益率對應的還款計劃
	 */
	private Map<BigDecimal, List<BizplanRepay>> bizplanRepayMap;
	
	/**
	 * 緩存不同年化收益率的還款計劃方案二
	 * 使用List集合:元素爲不同年化收益率的還款計劃
	 */
	private List<List<BizplanRepay>> bizplanRepayLists;
	
	/**
	 * 合併後的還款計劃
	 */
	private List<BizplanRepay> bizplanRepayList;
	
	/**
	 * 初始化
	 *
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午2:24:11
	 */
	@Before
	public void Init() {
		bizplanRepayList1 = new ArrayList<>();
		bizplanRepayList1.add(new BizplanRepay(1, new BigDecimal("60.00"), new BigDecimal("60.00"), new BigDecimal("0.62")));
		bizplanRepayList1.add(new BizplanRepay(2, new BigDecimal("70.00"), new BigDecimal("70.00"), new BigDecimal("0.78")));
		bizplanRepayList2 = new ArrayList<>();
		bizplanRepayList2.add(new BizplanRepay(1, new BigDecimal("25.00"), new BigDecimal("25.00"), new BigDecimal("0.05")));
		bizplanRepayList2.add(new BizplanRepay(2, new BigDecimal("20.00"), new BigDecimal("20.00"), new BigDecimal("0.04")));
		bizplanRepayList3 = new ArrayList<>();
		bizplanRepayList3.add(new BizplanRepay(1, new BigDecimal("15.00"), new BigDecimal("15.00"), new BigDecimal("0.17")));
		bizplanRepayList3.add(new BizplanRepay(2, new BigDecimal("10.00"), new BigDecimal("10.00"), new BigDecimal("0.12")));
		//-- 初始化bizplanRepayMap
		bizplanRepayMap = new HashMap<>();
		bizplanRepayMap.put(new BigDecimal("0.05"), bizplanRepayList1);
		bizplanRepayMap.put(new BigDecimal("0.10"), bizplanRepayList2);
		bizplanRepayMap.put(new BigDecimal("0.15"), bizplanRepayList3);
		//-- 初始化bizplanRepayLists
		bizplanRepayLists = new ArrayList<>();
		bizplanRepayLists.add(bizplanRepayList1);
		bizplanRepayLists.add(bizplanRepayList2);
		bizplanRepayLists.add(bizplanRepayList3);
	}

	/**
	 * 用於遍歷合併後的還款計劃
	 *
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午2:28:07
	 */
	@After
	public void forEach() {
		bizplanRepayList.forEach(bizplanRepay -> {
			System.out.println("還款計劃當前期數:" + bizplanRepay.getPeriodNumber());
			System.out.println("計息本金:" + bizplanRepay.getInterestPrincipal());
			System.out.println("本金:" + bizplanRepay.getPrincipal());
			System.out.println("利息:" + bizplanRepay.getInterest());
		});
	}
	
	/**
	 * 方案一:
	 * 使用JDK API
	 * 
	 * 使用到的API:
	 * Map<K,V>(interface)
	 * Set<K> keySet();
	 * 
	 * Collection<E>(interface)
	 * default Stream<E> stream() {
	 *      return StreamSupport.stream(spliterator(), false);
	 * }
	 * 
	 * Stream<T>(interface)
	 * <R, A> R collect(Collector<? super T, A, R> collector);
	 * 
	 * Collectors(final class)
	 * public static <T> Collector<T, ?, List<T>> toList() {
	 *	        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
	 *	                                   (left, right) -> { left.addAll(right); return left; },
	 *	                                   CH_ID);
	 *	}
	 *
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午2:29:15
	 */
	@Test
	public void testMergeList1() {
		//-- 1、獲取key的List集合
		//-- 使用JDK API 將Set集合轉換爲List集合
		List<BigDecimal> keyList = new ArrayList<>(bizplanRepayMap.keySet());
		//-- 使用JDK8 Stream API 將Set集合轉換爲List集合
		//List<BigDecimal> keyList = bizplanRepayMap.keySet().stream().collect(Collectors.toList());
		
		//-- 2、以第一個List爲基準組裝對象參數
		List<BizplanRepay> mergeBizplanRepayList = bizplanRepayMap.get(keyList.get(0));
		
		//-- 3、組裝每期計息本金、本金、利息
		for (int i = 0; i < mergeBizplanRepayList.size(); i++) {
			for (int j = 1; j < keyList.size(); j++) {
				List<BizplanRepay> otherBizplanRepayList = bizplanRepayMap.get(keyList.get( j));
				//-- 3.1、組裝計息本金
				mergeBizplanRepayList.get(i).setInterestPrincipal(mergeBizplanRepayList.get(i).getInterestPrincipal()
						.add(otherBizplanRepayList.get(i).getInterestPrincipal()));
				//-- 3.2、組裝本金
				mergeBizplanRepayList.get(i).setPrincipal(mergeBizplanRepayList.get(i).getPrincipal()
						.add(otherBizplanRepayList.get(i).getPrincipal()));
				//-- 3.3、組裝利息
				mergeBizplanRepayList.get(i).setInterest(mergeBizplanRepayList.get(i).getInterest()
						.add(otherBizplanRepayList.get(i).getInterest()));
			}
		}
		
		//-- 4、賦值
		bizplanRepayList = mergeBizplanRepayList;
	}
	
	/**
	 * 方案一:
	 * 使用JDK8 Stream API
	 * 
	 * 使用到的API:
	 * Map<K,V>(interface)
	 * Collection<V> values();
	 * 
	 * Collection<E>(interface)
	 * default Stream<E> stream() {
	 *      return StreamSupport.stream(spliterator(), false);
	 * }
	 * 
	 * Stream<T>(interface)
	 * Optional<T> reduce(BinaryOperator<T> accumulator);
	 * reduce是歸約的含義
	 * 
	 * Optional<T>(final class)
	 * public T get() {
	 *      if (value == null) {
	 *          throw new NoSuchElementException("No value present");
	 *      }
	 *      return value;
	 * }
	 * 
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午3:01:19
	 */
	@Test
	public void testMergeList2() {
		 bizplanRepayList = bizplanRepayMap.values()
										                              .stream()
										                              .reduce(
										                            		  (bizplanRepayList1, bizplanRepayList2) -> {
																				  for (int i = 0; i < bizplanRepayList1.size(); i++) {
																					  //-- 組裝計息本金
																					  bizplanRepayList1.get(i).setInterestPrincipal(
																							  bizplanRepayList1.get(i).getInterestPrincipal()
																							  .add(bizplanRepayList2.get(i).getInterestPrincipal()));
																					  //-- 組裝本金
																					  bizplanRepayList1.get(i).setPrincipal(
																							  bizplanRepayList1.get(i).getPrincipal()
																							  .add(bizplanRepayList2.get(i).getPrincipal()));
																					  //-- 組裝利息
																					  bizplanRepayList1.get(i).setInterest(
																							  bizplanRepayList1.get(i).getInterest()
																							  .add(bizplanRepayList2.get(i).getInterest()));
																				  }
																				  return bizplanRepayList1;})
										                              .get();
	}
	
	/**
	 * 方案二:
	 * 使用JDK API
	 * 
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午3:03:28
	 */
	@Test
	public void testMergeList3() {
		//-- 1、以第一個List爲基準組裝對象參數
		List<BizplanRepay> mergeBizplanRepayList = bizplanRepayLists.get(0);
		
		//-- 2、組裝每期計息本金、本金、利息
		for (int i = 0; i < mergeBizplanRepayList.size(); i++) {
			for (int j = 1; j < bizplanRepayLists.size(); j++) {
				List<BizplanRepay> otherBizplanRepayList = bizplanRepayLists.get(j);
				//-- 2.1、組裝計息本金
				mergeBizplanRepayList.get(i).setInterestPrincipal(mergeBizplanRepayList.get(i).getInterestPrincipal()
						.add(otherBizplanRepayList.get(i).getInterestPrincipal()));
				//-- 2.2、組裝本金
				mergeBizplanRepayList.get(i).setPrincipal(mergeBizplanRepayList.get(i).getPrincipal()
						.add(otherBizplanRepayList.get(i).getPrincipal()));
				//-- 2.3、組裝利息
				mergeBizplanRepayList.get(i).setInterest(mergeBizplanRepayList.get(i).getInterest()
						.add(otherBizplanRepayList.get(i).getInterest()));
			}
		}
		
		//-- 3、賦值
		bizplanRepayList = mergeBizplanRepayList;
	}
	
	/**
	 * 方案二:
	 * 使用JDK Stream API
	 * 
	 * 使用到的API
	 * Collection<E>(interface)
	 * default Stream<E> stream() {
	 *      return StreamSupport.stream(spliterator(), false);
	 * }
	 * 
	 * Stream<T>(interface)
	 * Optional<T> reduce(BinaryOperator<T> accumulator);
	 * reduce是歸約的含義
	 * 
	 * Optional<T>(final class)
	 * public T get() {
	 *      if (value == null) {
	 *          throw new NoSuchElementException("No value present");
	 *      }
	 *      return value;
	 * }
	 *
	 * @author hongwei.lian
	 * @date 2018年5月19日 下午3:07:20
	 */
	@Test
	public void testMergeList4() {
		bizplanRepayList = bizplanRepayLists.stream()
										                             .reduce(
															      		     (bizplanRepayList1, bizplanRepayList2) -> {
																				 for (int i = 0; i < bizplanRepayList1.size(); i++) {
																					  //-- 組裝計息本金
																					  bizplanRepayList1.get(i).setInterestPrincipal(
																							  bizplanRepayList1.get(i).getInterestPrincipal()
																							  .add(bizplanRepayList2.get(i).getInterestPrincipal()));
																					  //-- 組裝本金
																					  bizplanRepayList1.get(i).setPrincipal(
																							  bizplanRepayList1.get(i).getPrincipal()
																							  .add(bizplanRepayList2.get(i).getPrincipal()));
																					  //-- 組裝利息
																					  bizplanRepayList1.get(i).setInterest(
																							  bizplanRepayList1.get(i).getInterest()
																							  .add(bizplanRepayList2.get(i).getInterest()));
																				  }
																				  return bizplanRepayList1;})
															         .get();
	}

}

最終採用方案二的JDK8實現方式



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章