在卓越网首页的左边,或者当当网的左边,都有商品分类列表,并会显示旗下的商品有多少种。如何在计算机中描述?那可定是用树来表示。但要高效地完成这个功能会面临哪些问题?
1、怎么统计某一分类的商品种类
2、如果更改某一分类商品种类数量,怎么通知其他节点
3、对于非叶子节,是否要记录商品数,
4、如果增加新的商品类型,又怎么做
对于这些问题,我认为关键的一点是:一旦有数据变化,就要通知双亲,直到根节点。这样一来,每当获取某一中分类的商品种类数时,它会检测是否收到通知,如果收到,则重新计算;否则直接返回数量。
2011年9月,引入CommodityVisitor和CommoditySearcher,用来处理遍历和检索两种情况;重写计算商品分类数量的相关函数;删除多余函数。
废话不多说,直接贴代码,欢迎拍砖。
/**
* 商品分类
*/
public class CommodityClassify implements Cloneable {
private static final int ZERO = 0;
//************************* 节点属性 ******************************
/**
* 该分类名称
*/
private String name;
/**
* 商品分数码
*/
private String code;
/**
* 该分类下的商品种类数
*/
private int amount = ZERO;
/**
* 是否要计算商品种类
*/
private boolean needRecount = true;
//*************************** 树形关系 *********************************
/**
* 双亲结点
*/
private CommodityClassify parent;
/**
* 孩子结点
*/
private List<CommodityClassify> children = Collections.synchronizedList(new LinkedList<CommodityClassify>());
public CommodityClassify(String name, String code) {
this(name, code, ZERO);
}
public CommodityClassify(String name, String code, int amount) {
this.name = name;
this.code = code;
this.amount = amount;
}
/**
* 调整节点的amount
*
* @param amount
*/
public synchronized void adjustAmount(int amount) {
//1、如果是叶子节点,则传入amount,否则跳过
if (isLeafy() && this.amount != amount) {
this.amount = amount;
onAmountChange();
}
}
/**
* 判断是否为叶子节点
*/
public boolean isLeafy() {
return 0 == children.size();
}
/**
* 计算当前节点的商品种类
*/
public int calcAmount() {
if (needRecount && !isLeafy()) {
amount = ZERO;
for (CommodityClassify cc : children) {
amount += cc.calcAmount();
}
needRecount = false;
}
return amount;
}
/**
* 返回深度
*
* @return
*/
public int getDepth() {
int depth = 1;
CommodityClassify root = parent;
while (root != null) {
depth += 1;
root = root.getParent();
}
return depth;
}
//************************* getter/setter ******************************
protected void setChildren(List<CommodityClassify> children) {
this.children = children;
}
public boolean isNeedRecount() {
return needRecount;
}
private void setNeedRecount(boolean needRecount) {
this.needRecount = needRecount;
}
public CommodityClassify getParent() {
return parent;
}
public void setParent(CommodityClassify parent) {
this.parent = parent;
}
public String getName() {
return name;
}
public String getCode() {
return code;
}
public List<CommodityClassify> getChildren() {
return children;
}
public int getAmount() {
return amount;
}
//********************* 节点操作 **********************
/**
* 增加孩子结点
* 需要同步
*
* @param cc
*/
private void addChild(CommodityClassify cc) {
//1、设置双亲节点
cc.setParent(this);
//2、增加叶子节点
children.add(cc);
onAmountChange();
}
/**
* 删除孩子节点
*
* @param cc
*/
private void removeChild(CommodityClassify cc) {
//1、待删除的节点清空双亲
cc.setParent(null);
//2、删除节点
children.remove(cc);
//3、通知变化
onAmountChange();
}
/**
* 返回根节点
*
* @return
*/
private CommodityClassify getRoot() {
CommodityClassify root = this;
while (root.parent != null) {
root = root.parent;
}
return root;
}
/**
* 商品分类的数量变化时,重新计算
*/
private void onAmountChange() {
notifyParentChange();
recountTotal();
}
/**
* 通知双亲结点:数据已经改变
*/
private void notifyParentChange() {
//通知当前当前结点数据变化
this.setNeedRecount(true);
//通知双亲结点数据已经变化
CommodityClassify parents = this.parent;
while (parents != null) {
parents.setNeedRecount(true);
parents = parents.parent;
}
}
/**
* 重新计算 商品 总数
*/
private void recountTotal() {
this.getRoot().calcAmount();
}
//************************* 遍历 **************************
/**
* 广度优先遍历
*/
public void breadthFirstTraversal(CommodityVisitor visitor) {
Queue<CommodityClassify> queue = new LinkedList<CommodityClassify>();
queue.add(this);
while (!queue.isEmpty()) {
CommodityClassify c = queue.poll();
visitor.visit(c);
queue.addAll(c.getChildren());
}
}
/**
* 返回层次遍历的的链表
*
* @return
*/
public List<CommodityClassify> getBFTList() {
List<CommodityClassify> list = new LinkedList<CommodityClassify>();
int currentIndex = 0;
list.add(this);
while (currentIndex < list.size()) {
if (!list.get(currentIndex).isLeafy()) {
list.addAll(list.get(currentIndex).getChildren()); ///将子节点添加的list中
}
currentIndex++;
}
return list;
}
/**
* 深度优先遍历 非递归算法 方向 :从右到左
*/
public void depthFirstTraversal(CommodityVisitor visitor) {
Stack<CommodityClassify> stack = new Stack<CommodityClassify>();
stack.push(this);
while (!stack.isEmpty()) {
CommodityClassify c = stack.pop();
visitor.visit(c);
if (!c.isLeafy()) {
stack.addAll(c.getChildren());
}
}
}
//************************* 检索 **************************
/**
* 广度优先检索
*/
public CommodityClassify breadthFirstSearch(CommoditySearcher searcher) {
Queue<CommodityClassify> queue = new LinkedList<CommodityClassify>();
queue.add(this);
while (!queue.isEmpty()) {
CommodityClassify c = queue.poll();
if (searcher.search(c)) {
return c;
}
queue.addAll(c.getChildren());
}
return null;
}
/**
* 深度优先检索
*/
public CommodityClassify depthFirstSearch(CommoditySearcher searcher) {
Stack<CommodityClassify> stack = new Stack<CommodityClassify>();
stack.push(this);
while (!stack.isEmpty()) {
CommodityClassify c = stack.pop();
if (searcher.search(c)) {
return c;
}
if (!c.isLeafy()) {
stack.addAll(c.getChildren());
}
}
return null;
}
//*************************** 常见操作 函数*******************************
/**
* 添加子商品分类
* @param name 分类名称
* @param code 分类编码
* @param amount 数量
* @return
*/
public CommodityClassify addChild(String name, String code, int amount) {
CommodityClassify c = new CommodityClassify(name, code, amount);
addChild(c);
return c;
}
public CommodityClassify addChild(String name, String code) {
CommodityClassify c = new CommodityClassify(name, code);
addChild(c);
return c;
}
public CommodityClassify getByCode(final String code) {
CommoditySearcher vs = new CommoditySearcher() {
public boolean search(CommodityClassify c) {
return (c.getCode().equals(code));
}
};
return depthFirstSearch(vs);
}
/**
* 把 当前树 从 整棵树中 剥离出来;
*/
public void remove() throws Exception {
if (this.getParent() == null) throw new Exception("根节点不能删除");
//1、找到双亲
parent = this.getParent();
//2、删除当前树
parent.removeChild(this);
}
/**
* 删除商品分类
* @param cc
* @throws Exception
*/
public void remove(CommodityClassify cc) throws Exception {
if (this.getParent() == null) throw new Exception("根节点不能删除");
if (this.equals(cc)) throw new Exception("不能删除自身");
if (!this.children.contains(cc)) throw new Exception("不包含子节点");
removeChild(cc);
}
//************************ 其他 ********************************************
public boolean equals(Object obj) {
if (obj == null) return false;
if (obj.getClass() != this.getClass()) return false;
CommodityClassify c = (CommodityClassify) obj;
return c.getCode().equals(this.getCode());
}
public Object clone() throws CloneNotSupportedException {
super.clone();
CommodityClassify c = new CommodityClassify(name, code, amount);
List<CommodityClassify> ccList = Collections.synchronizedList(new LinkedList<CommodityClassify>());
for (CommodityClassify cc : children) {
CommodityClassify newCC = (CommodityClassify) cc.clone();
newCC.setParent(c);
ccList.add(newCC);
}
c.setChildren(ccList);
return c;
}
}
public interface CommoditySearcher {
public boolean search(CommodityClassify c);
}
public interface CommodityVisitor {
public void visit(CommodityClassify cc);
}
分享到:
相关推荐
这份名为“京东商城商品分类数据.zip”的压缩包文件内包含了一个名为“京东商城商品分类数据.xlsx”的Excel表格,它为我们揭示了京东商城内部的商品分类体系和结构,是理解电商运营、市场分析以及商品管理的重要参考...
通过SQL文件,我们可以深入理解淘宝的商品分类体系,甚至可以进行各种数据分析,例如统计各个类别的商品数量、分析各级别目录下的商品分布等。这样的数据对于电商从业者、市场分析师、数据科学家以及对电商有兴趣的...
在选择的商品分类中检索出需要的商品分类名称和编号,勾选前面方框(可多选),确认选择,选中商品分类在 中显示,点击,按照所选商品筛选检索,也可将所选存为自己的。 按报告国家检索选择报告国家来源,全部/用户...
总的来说,这个"淘宝网商品分类"数据集为研究淘宝商品生态、电商运营策略提供了宝贵的资源,对于数据分析师、电商从业者以及对电商市场感兴趣的个人都有着极高的价值。通过深入挖掘和利用这些数据,我们可以更深入地...
这个Java商品分类系统的设计和实现主要用于超市商品的管理,包括水果、蔬菜、肉类和零食的分类信息。系统的核心类`GoodsManager`使用ArrayList存储`Goods`对象,实现了商品的增删改查以及统计功能。 1. **添加商品*...
例如,库存管理系统会根据商品分类进行库存的分类统计,订单处理会根据分类来打包和发货,而搜索索引则会基于分类进行关键词匹配,提高搜索效率。因此,理解并有效利用这些分类数据对于优化京东商城的运营至关重要。
标签“淘宝分类”、“淘宝商品分类”、“商品分类”强调了数据的核心内容,即与淘宝平台上的商品分类有关,涵盖了广泛的商品信息。 压缩包文件名为“taobao20190803003338”,可能是以日期和时间戳命名,便于管理和...
超市商品分类是零售业管理的重要环节,旨在提升运营效率,优化顾客购物体验。商品分类主要遵循三大原则:大分类、中分类和小分类。 大分类是最高级别的分类,通常不超过十个,依据商品的特性,如生产来源、生产方式...
【商品分类编码与商业自动化】 商品分类编码是商业自动化中不可或缺的一部分,它的主要目标是将商品信息用标准化的符号体系表示出来,便于计算机处理和人类理解。随着科技的快速发展,信息处理的需求日益增长,自动...
3. 联合国国际贸易标准分类(SITC):另一种国际性的商品分类系统,主要用于统计目的。 4. 对外贸易进口业务统计商品目录:特定国家或地区的进口商品分类目录。 商品条码的使用流程通常包括: 1. 申请厂商代号:...
- 对外贸易:从单个国家或地区的视角,包括出口和进口,以及过境贸易(商品经过该国但不消费于此)。 - 区域贸易:几个国家或地区间的贸易互动。 - 国际贸易:全球范围内的商品和服务交换。 3. **基本统计指标**...
《商品分类规则PPT学习教案》是一份详细阐述商品分类及其重要性的教学材料,主要针对的是专业领域的知识,包括零售管理、供应链管理以及信息管理等多个方面。商品分类是商业运营中的核心环节,对于企业的决策制定、...
- 商品分类统计:统计各类商品的数量,提供销售决策参考。 5. 用户界面设计: 虽然C语言不擅长图形用户界面(GUI)开发,但可以通过命令行交互方式实现简单的操作界面。使用`printf`和`scanf`进行输入输出交互,...
- 用户可以通过这个数据库获取各国的贸易总量数据,包括进口、出口以及按商品分类的数据。 - BEC分类系统用于商品的详细分类,便于深入分析特定产品的贸易行为。 - 数据可以按照时间序列分析,揭示贸易趋势和经济...
《第十一章 商品流通与外贸统计》主要涵盖了四个核心领域:商品供需统计、商品流转统计、商品价格统计以及对外贸易统计。以下将详细介绍这些领域的关键知识点。 首先,商品供需统计是研究商品从生产到消费过程中的...
在商品检索中,用户可以选择商品分类,输入关键词搜索商品名称,或者通过商品分类编码进行查找。报告国家和交易国家的检索同样灵活,支持多选和自定义国家群体。年份检索允许用户按特定年份或年份范围进行筛选。此外...
国际贸易商品分类是全球经济活动中至关重要的一个环节,它用于标准化不同国家间商品的识别、统计和关税征收。在国际贸易中,有几种主要的商品分类系统被广泛采用,这些系统为全球贸易的顺畅运作提供了基础。 首先,...
《连锁超市商品分类明细表》是对超市经营商品进行精细化管理的重要工具,主要用于规范商品的存储、销售和统计工作。这份文档详细列出了商品的分类体系,涵盖了食品、饮料烟酒、副食、粮油、生鲜、日配、散装加工、...