代码效率太低,货品一多会导致内存溢出.求优化或给出更好的解决方案
package com.example.demo.box;
import java.util.*;
public class GoodsInBox {
/*箱子的型号,盛放空间*/
private Map<Integer,Map<String,Object>> boxTypeArr;
/*订单中的商品*/
private Map<Integer,Map<String,Integer>> orderItemArr;
/*计算结果*/
private Map<String /*箱子型号*/,Integer/*需要几个*/> result=new HashMap<String,Integer>();
/*计算过程数据,有效的空间列表*/
private List<String> inboxinfo=new ArrayList<String>();
/**
* 根据箱型以及订单中的商品,返回每个箱型需要箱子多少只。如果没有任何的箱子能装下某一款超大商品的时候,抛出异常
*
* @param linkedHashMap
* @param orderItemArr
* @return
*/
public GoodsInBox(LinkedHashMap<Integer, Map<String, Object>> linkedHashMap, Map<Integer, Map<String, Integer>> orderItemArr){
this.boxTypeArr = linkedHashMap;
this.orderItemArr=orderItemArr;
//开始执行
run();
}
/**
* boxType.get(boxkey) value{boxcode=1, l=100, w=100, h=120}
* boxType.get(boxkey) {boxcode=2, l=200, w=150, h=180}
* boxType.get(boxkey) {boxcode=3, l=500, w=600, h=700}
*/
//执行装箱
private void run(){
Integer[] boxkeys=boxTypeArr.keySet().toArray(new Integer[]{});
aBoxType: for (Integer boxkey : boxkeys) {
tryInSpance(boxTypeArr.get(boxkey), orderItemArr);
}
}
/**
* 每次测试1块空间,和全部商品,将商品一次向空间转移,放进去后产生新的3块空间,同时商品的数量再减少,直到商品全部转移;
* @param boxMap
* @param products
*/
private void tryInSpance(Map<String/* 长l宽w高h */, Object/* 厘米 */> boxMap/* 某1个盒子或者是1个剩餘空間 */,
Map<Integer, Map<String, Integer>> products/* 多件商品,装进去一件,删除一件,直到删没了为止 */){
if (null == boxMap || null == products) {
return;
}
java.util.Iterator<Integer> gks = products.keySet().iterator(); //对存储商品的Map进行遍历
while (gks.hasNext()) {
Integer oid = gks.next(); //oid就是products的Key
Map<String, Integer> g = products.get(oid); //g是具体的商品属性
// 商品数量
Integer num = g.get("n"); //获取某种商品的数量
if (0 == num) {
return;
}
// 多少件商品就循环多少次,每次处理一件;
for (int i = num; i > 0; i--) {
String boxcode = boxMap.get("boxcode").toString().concat(":").concat(oid.toString()); //箱的Kye:商品的Key 1:1
Integer bl = Integer.valueOf(boxMap.get("l").toString()); //箱的长
Integer bw = Integer.valueOf(boxMap.get("w").toString()); //箱的宽
Integer bh = Integer.valueOf(boxMap.get("h").toString()); //箱的高
Integer gl = g.get("l"); //商品的长
Integer gw = g.get("w"); //商品的宽
Integer gh = g.get("h"); //商品的高
// 正面放置商品
if ((bl - gl) >= 0 && (bw - gw) >= 0 && (bh - gh) >= 0) {
// 可以放入的情况下先减少商品的数量;
g.put("n", i - 1);
// 加入统计
inboxinfo.add(boxcode);
// 正放的3块剩余空间
Map<String, Object> leftover;
// 第一块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
leftover.put("l", gl);
leftover.put("w", gw);
leftover.put("h", bh - gh);
tryInSpance(leftover, products);
// 第二块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
leftover.put("l", gl);
leftover.put("w", bw - gw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 第三块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
leftover.put("l", bl - gl);
leftover.put("w", bw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 侧面放置商品
} else if ((bl - gw) >= 0 && (bw - gl) >= 0 && (bh - gh) >= 0) {
// 可以放入的情况下先减少商品的数量;
g.put("n", i - 1);
// 加入统计
inboxinfo.add(boxcode);
// 侧放的3块剩余空间
Map<String, Object> leftover;
// 第一块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
leftover.put("l", gl);
leftover.put("w", gw);
leftover.put("h", bh - gh);
tryInSpance(leftover, products);
// 第二块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
leftover.put("l", bw - gl);
leftover.put("w", gw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 第三块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
leftover.put("l", bl - gw);
leftover.put("w", bw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 卧倒放置商品
} else if (g.get("t") == 1 && (bl - gh) >= 0 && (bw - gw) >= 0 && (bw - gl) >= 0) {
// 可以放入的情况下先减少商品的数量;
g.put("n", i - 1);
// 加入统计
inboxinfo.add(boxcode);
// 侧放的3块剩余空间
Map<String, Object> leftover;
// 第一块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
leftover.put("l", gh);
leftover.put("w", gw);
leftover.put("h", bh - gh);
tryInSpance(leftover, products);
// 第二块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
leftover.put("l", bw - gw);
leftover.put("w", gh);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 第三块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
leftover.put("l", bl - gh);
leftover.put("w", bw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 侧卧放置商品
} else if (g.get("t") == 1 && (bl - gw) >= 0 && (bh - gl) >= 0 && (bw - gh) >= 0) {
// 可以放入的情况下先减少商品的数量;
g.put("n", i - 1);
// 加入统计
inboxinfo.add(boxcode);
// 侧放的3块剩余空间
Map<String, Object> leftover;
// 第一块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-1:").concat(oid.toString()));
leftover.put("l", gw);
leftover.put("w", gh);
leftover.put("h", bh - gl);
tryInSpance(leftover, products);
// 第二块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-2:").concat(oid.toString()));
leftover.put("l", bw - gh);
leftover.put("w", gw);
leftover.put("h", bh);
tryInSpance(leftover, products);
// 第三块空间
leftover = new HashMap<String, Object>();
leftover.put("boxcode", boxcode.concat("-3:").concat(oid.toString()));
leftover.put("l", bl - gw);
leftover.put("w", bw);
leftover.put("h", bh);
tryInSpance(leftover, products);
}
}
}
}
/**
* 返回计算后得到的结果
* @return
*/
public Map<String/* 箱子的型号 */, Integer/* 需要几个 */> getResult(){
result.clear();
// 这里开始数数了!
// 所有装入盒子的商品都放到列表中了,
// length为特定长度(3)的为商品第一次装入箱子,其它过长(>3)的都是小件商品塞到之前的箱子里的。
// 以上运行的结果应该是:最少需要1号箱两个,3号箱1个,
for (String code : inboxinfo) {
if (code.length() == 3) {
String boxno = String.valueOf(code.split(":")[0]);
Integer num = result.get(boxno);
if (null == num)
num = 0;
num = num + 1;
result.put(boxno + "", num);
}
}
return this.result;
}
public static void main(String[] arproducts) {
GoodsInBox gb = new GoodsInBox(/* 箱子的规格 */new LinkedHashMap<Integer, Map<String, Object>>() {
{
// 假设有大中小三种型号的箱子,如下描述:
/*-
* 要求数据从数据库中取出来的时候是按照 箱子型号大小系数 (l长+w款+h高) 从小到大的顺序排好序的。這樣裝箱后可以得到近似合理的解
*/
// 1,小箱
this.put(1, new LinkedHashMap<String, Object>() {
{
// 小箱 长 100厘米,宽100厘米,高120厘米;
this.put("boxcode", 1);
this.put("l", 100);
this.put("w", 100);
this.put("h", 120);
}
});
// 2,中箱
this.put(2, new LinkedHashMap<String, Object>() {
{
// 中箱 长200厘米,宽150厘米,高180厘米
this.put("boxcode", 2);
this.put("l", 200);
this.put("w", 150);
this.put("h", 180);
}
});
// 3,大箱
this.put(3, new LinkedHashMap<String, Object>() {
{
// 大箱长500厘米宽600厘米高700厘米
this.put("boxcode", 3);
this.put("l", 500);
this.put("w", 600);
this.put("h", 700);
}
});
}
}, /* 订单 */ new LinkedHashMap<Integer, Map<String, Integer>>() {
{
/*-
* 要求数据从数据库中取出来的时候是按照 商品大小系数 (l长+w款+h高) 从大到小的顺序排好序的。這樣裝箱后可以得到近似合理的解
*/
// 1,卧室用的小冰箱1个
this.put(1, new LinkedHashMap<String, Integer>() {
{
// 长 400厘米,宽500厘米,高600厘米;
this.put("l", 400);
this.put("w", 500);
this.put("h", 600);
this.put("n", 10);
this.put("t", 0);// 是否可以躺着放,0,否;1,是,这个不能躺着放,而且所有商品均不能倒置,而且倒置和正着放置所占用空间一样。
}
});
// 1,电脑主机箱2台
this.put(2, new LinkedHashMap<String, Integer>() {
{
// 长 57厘米,宽21厘米,高52厘米;
this.put("l", 1);
this.put("w", 1);
this.put("h", 1);
this.put("n", 5);
this.put("t", 1);// 是否可以躺着放,0,否;1,是
}
});
// 2,苹果笔记本电脑10台
this.put(3, new LinkedHashMap<String, Integer>() {
{
// 长 33厘米,宽24厘米,高6厘米;
this.put("l", 1);
this.put("w", 1);
this.put("h", 1);
this.put("n", 5);
this.put("t", 1);// 是否可以躺着放,0,否;1,是
}
});
}
});
// 1号箱子 2只,分别装笔记本和小键盘; 3号箱子:1只用来装冰箱
System.out.println(gb.getResult().toString());
}
}