天天看點

java遞歸循環跳出案例分析

前言:藥店售藥環節,醫保刷卡存在特殊需求,頁面錄入任意金額T元,要求查詢出總價為T(或者略大于T)的貨品組合。

判斷邏輯:

1)根據醫保目錄随機選取同等價格商品(可略大于,但不能超過15%)

2)20元以内選取一個商品、50元以内最少選取二個商品、100元以内最少選取三個商品

3)超過100元,以上面三種方法遞增

需求分析:

0-20元檔 錄入任意金額,查出一個貨品,貨品價格區間為[0,20];

20-50元檔 錄入任意金額x,查出最少2個貨品,貨品價格總和為x;

50-100元檔 錄入任意金額y,查出最少3個貨品,貨品價格總和為y;

100-n元檔,錄入任意金額z,查出上述邏輯計算出的貨品數量,貨品價格總和為z;

代碼:

package day09;

import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;

import com.inca.np.gui.control.DBTableModel;
import com.inca.np.util.DecimalHelper;
import com.inca.np.util.SelectHelper;
import com.inca.pubsrv.ObjectUtils;
import com.inca.resale.sale.ybkp.server.GoodsqtyhovService.ZxException;

/**
 * @author Yudx
 * @date 2020年3月7日 上午10:41:35
 */
public class RecursionDemo {
	/**
	 * @param con
	 * @param wheres
	 * @param yushu1 
	 * @return
	 * add by yudexiao
	 * 2020年3月4日 下午9:31:35
	 * @throws Exception 
	 */
	private DBTableModel getT2Model(Connection con, String shang1, String wheres) throws Exception {
		DBTableModel t2Model = null;
		Map<String, String> map = new HashMap<String, String>();
		/**
		 * 假設我們要擷取一個40元的貨品,該貨品價格區間在[20,50]這段内,
		 * 那我們先從區間[10,40]價格段随機擷取一個貨品,
		 * 假設取到 的随機數是x,那麼 取另一個貨品價格則為40-x,
		 * 然後從結果集中查詢擷取價格為40-x的貨品,如果有則取出,如果沒有則遞歸,重新随機擷取一個貨品,
		 * 假設取到 的随機數是y,那麼 取另一個貨品價格則為40-y,
		 * 然後從結果集中查詢擷取價格為40-y的貨品,如果有則取出,如果沒有則遞歸。
		 */
		String ssql = "select b.goodsid, x.price\n" +
				"  from npbusi_yb_goods     a,\n" + 
				"    npbusi_yb_goods_ref b,\n" + 
				"    (select price,priceid,goodsid from ngpcs_all_price where placepointid = "+placepointid+") x,\n" + 
				"    pub_price_type      c\n" + 
				" where a.ybgoodsid = b.ybgoodsid\n" + 
				"   and x.priceid = c.priceid\n" + 
				"   and x.goodsid = b.goodsid\n" + 
				"   and c.pricename = '公司零售價'\n" + 
				"   and c.workflag in (4, 5)\n" + 
				"  and nvl(x.price, 0) >10 and nvl(x.price, 0) < "+shang1+" \n" + 
				"   and exists (select 1 from Npbusi_yb_company\n" + 
				"         where ybid = b.ybid and companyid = "+placepointid+")\n";
		ssql = ssql + " and " + wheres ;
		SelectHelper sh = new SelectHelper(ssql);//擷取複核條件的sql
		DBTableModel goodsdm = null;
		goodsdm = sh.executeSelect(con, 0, 10);
		if (!ObjectUtils.isNULL(goodsdm)) {
			for (int i = 0; i < goodsdm.getRowCount(); i++) {
				map.put(goodsdm.getItemValue(i, "goodsid"), goodsdm.getItemValue(i, "price"));
			}
		}
		String randomGoodsid = getRandomKeyFromMap(map);//将貨品價格放到map中随機擷取一個goodsid
		String randomPrice = map.get(randomGoodsid);
		//求內插補點
		String param = DecimalHelper.toDec(shang1).subtract(DecimalHelper.toDec(randomPrice)).toString();
		//遞歸取另外一個貨品
		DBTableModel zxmodel = null;
		try {
			getSpecialModel(con,param,wheres,map,randomGoodsid,randomPrice,shang1);
		} catch (ZxException e) {
			//異常處理比較罕見,這裡要重點注意,跳出遞歸,此處我用到的方法是:抛異常
			zxmodel = e.getModel();
		} catch (Exception e) {
			e.printStackTrace();
		}
		t2Model = zxmodel.copyStruct();
		t2Model.bindMemds(zxmodel);
		return t2Model;
	}
	
	class ZxException extends Exception{
		private DBTableModel model ;
		/**
		 * @return the model
		 */
		public DBTableModel getModel() {
			return model;
		}
		/**
		 * @param model the model to set
		 */
		public void setModel(DBTableModel model) {
			this.model = model;
		}

		private ZxException (DBTableModel zxmodel) {
			this.model = zxmodel;
		}
	}
	
	
	/**
	 * @param map 
	 * @param wheres 
	 * @param param 
	 * @param con 
	 * @param shang1 
	 * @param randomPrice2 
	 * @param randomGoodsid2 
	 * @return
	 * add by yudexiao
	 * 2020年3月5日 上午10:26:27
	 * @throws Exception 
	 */
	private DBTableModel getSpecialModel(Connection con, String param, String wheres, Map<String, String> map, 
			String randomGoodsid, String randomPrice, String shang1) throws Exception {
		String theThirdSql = "select goodsid,price from ( select b.goodsid, x.price\n" +
				"  from npbusi_yb_goods     a,\n" + 
				"    npbusi_yb_goods_ref b,\n" + 
				"    (select price,priceid,goodsid from ngpcs_all_price where placepointid = "+placepointid+") x,\n" + 
				"    pub_price_type      c\n" + 
				" where a.ybgoodsid = b.ybgoodsid\n" + 
				"   and x.priceid = c.priceid\n" + 
				"   and x.goodsid = b.goodsid\n" + 
				"   and c.pricename = '公司零售價'\n" + 
				"   and c.workflag in (4, 5)\n" + 
				"   and nvl(x.price, 0) = " +param +  
				"   and exists (select 1 from Npbusi_yb_company where ybid = b.ybid and companyid = "+placepointid+")\n"
				+ " and " + wheres +"order by x.price asc ) where rownum = 1";
		SelectHelper sh = new SelectHelper(theThirdSql);
		System.out.println(param+"--"+theThirdSql);
		DBTableModel theThirdModel = sh.executeSelect(con, 0, 1);
		if (ObjectUtils.isNULL(theThirdModel)) {
			randomGoodsid = getRandomKeyFromMap(map);
			randomPrice = map.get(randomGoodsid);
			//求內插補點
			param = DecimalHelper.toDec(shang1).subtract(DecimalHelper.toDec(randomPrice)).toString();
			getSpecialModel(con,param,wheres,map,randomGoodsid,randomPrice,shang1);
		}else {
			DBTableModel firstModel = theThirdModel.copyStruct();
			firstModel.appendRow();
			firstModel.setItemValue(0, "goodsid", randomGoodsid);
			firstModel.setItemValue(0, "price", randomPrice);
			theThirdModel.bindMemds(firstModel);
			//采用一個抛自定義異常的方式,傳回該方法的傳回值。
			throw new ZxException(theThirdModel);
			//return theThirdModel;------------這種寫法有bug,無法正确跳出遞歸
		}
		return null;
	}
	
	class DBTableModel {
		
	}
	
}
           

總結:跳出遞歸需要用抛異常的方式,mark一下。

這個算法思路可以總結一下,化整為零,化零為整。