我有一个具有以下结构的数据库表:
CREATE TABLE `Professions` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`profession` varchar(254) NOT NULL,
`profession_type` enum('system','custom') NOT NULL,
PRIMARY KEY (`id`),
KEY `profession_index` (`profession`)
) ENGINE=InnoDB AUTO_INCREMENT=296 DEFAULT CHARSET=utf8
CREATE TABLE `Professions_Professions` (
`parent_id` bigint(20) unsigned NOT NULL,
`child_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`parent_id`,`child_id`),
UNIQUE KEY `child_id_UNIQUE` (`child_id`),
KEY `parent_id_index` (`parent_id`),
CONSTRAINT `fk_Professions_Professions1` FOREIGN KEY (`parent_id`) REFERENCES `Professions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_Professions_Professions2` FOREIGN KEY (`child_id`) REFERENCES `Professions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
为了获得专业的整个结构,我编写了以下 SQL:
SELECT id, profession, profession_type, parent_id FROM Professions P LEFT OUTER JOIN Professions_Professions PP ON PP.child_id = P.id;
现在,我想在 Java 应用程序中表示这种类型的结构(我的位置表结构几乎相同)。
对我来说,创建某种没有根的树看起来很合理,但它是一个充当根的元素列表。每个元素都将实现“节点”接口,该接口将允许获取其父元素和子元素列表。由于这应该是通用解决方案,我希望有一个通用树。
我也想有一个程序在这棵树中上下走动并执行一些可以返回的动作(接口)(在每个孩子和每个孩子列表上 - '节点'和'节点列表'动作)某个值与否,并且可以采用任意数量的参数。
如果动作将有一个返回值,我希望它的返回类型由动作实现指定。
我试图实现这一点并最终得到以下代码(应该有很多kludges ...):
// Removed the generic because i was unable to figure out how to make it all work ...
public interface TreeNode {
public void setParent(Object parent);
public void setChildList(List childList);
public Object getParent();
public List getChildList();
}
public class Tree<T extends TreeNode> {
private List<T> tree;
public Tree(List<T> treeNodeList) {
/* Ensuse that the list is not empty */
if((null != treeNodeList) && (!treeNodeList.isEmpty())) {
tree = new ArrayList<T>();
/* Link the elements and create the tree */
for(T node:treeNodeList) {
/* If the current node has a parent */
if(null != node.getParent()) {
/* Look the actual parent object in the initial node list */
int parentIndex = treeNodeList.indexOf(node.getParent());
if(-1 != parentIndex) {
T parent = treeNodeList.get(parentIndex);
/* Set the actual parent */
node.setParent(parent);
/* Add node to parent children list */
if(null == parent.getChildList()) {
parent.setChildList(new ArrayList<T>());
}
parent.getChildList().add(node);
}
}
else {
/* Add element to tree root list */
tree.add(node);
}
}
}
}
public List<?> getRootList() {
return tree;
}
public void forEachChild(List<T> rootList, SimpleNodeTreeAction<T> action, Object... args) {
if((null != rootList) && (!rootList.isEmpty())) {
Object[] localArgs = null;
for(T node:rootList) {
/* Store the local copy of args */
if(null != args) {
localArgs = args.clone();
}
action.doAction(node, localArgs);
forEachChild(node.getChildList(), action, localArgs);
}
}
}
public void forEachChild(T rootNode, SimpleNodeTreeAction<T> action, Object... args) {
if(null != rootNode) {
forEachChild(rootNode.getChildList(), action, args);
}
}
public void forEachChild(SimpleNodeTreeAction<T> action, Object... args) {
forEachChild(tree, action, args);
}
public Object forEachChild(List<T> rootList, NodeTreeAction<T> action, Object... args) {
Object result = null;
if((null != rootList) && (!rootList.isEmpty())) {
Object[] localArgs = null;
for(T node:rootList) {
/* Store the local copy of args */
if(null != args) {
localArgs = args.clone();
}
result = action.doAction(node, localArgs);
if(null == result) {
result = forEachChild(node.getChildList(), action, localArgs);
if(null != result) {
break;
}
}
else {
break;
}
}
}
return result;
}
public Object forEachChild(T rootNode, NodeTreeAction<T> action, Object... args) {
Object result = null;
if(null != rootNode) {
result = forEachChild(rootNode.getChildList(), action, args);
}
return result;
}
public Object forEachChild(NodeTreeAction<T> action, Object... args) {
return forEachChild(tree, action, args);
}
public void forEachChildList(List<T> rootList, SimpleNodeListTreeAction<T> action, Object... args) {
if((null != rootList) && (!rootList.isEmpty())) {
action.doAction(rootList, args);
for(T node:rootList) {
forEachChildList(node.getChildList(), action, args);
}
}
}
public void forEachChildList(T rootNode, SimpleNodeListTreeAction<T> action, Object... args) {
if(null != rootNode) {
forEachChildList(rootNode.getChildList(), action, args);
}
}
public void forEachChildList(SimpleNodeListTreeAction<T> action, Object... args) {
forEachChildList(tree, action, args);
}
public Object forEachChildList(List<T> rootList, NodeListTreeAction<T> action, Object... args) {
Object result = null;
if((null != rootList) && (!rootList.isEmpty())) {
result = action.doAction(rootList, args);
if(null == result) {
for(T node:rootList) {
result = action.doAction(node.getChildList(), args);
if(null != result) {
break;
}
}
}
}
return result;
}
public Object forEachChildList(T rootNode, NodeListTreeAction<T> action, Object... args) {
Object result = null;
if(null != rootNode) {
result = forEachChildList(rootNode.getChildList(), action, args);
}
return result;
}
public Object forEachChildList(NodeListTreeAction<T> action, Object... args) {
return forEachChildList(tree, action, args);
}
public void forEachParent(T rootNode, SimpleNodeTreeAction<T> action, Object... args) {
if(null != rootNode) {
T parent = (T) rootNode.getParent();
while(null != parent) {
action.doAction(parent, args);
parent = (T) parent.getParent();
}
}
}
public Object forEachParent(T rootNode, NodeTreeAction<T> action, Object... args) {
Object result = null;
if(null != rootNode) {
T parent = (T) rootNode.getParent();
while(null != parent) {
result = action.doAction(parent, args);
if(null == result) {
parent = (T) parent.getParent();
}
else {
break;
}
}
}
return result;
}
public Object search(final T searchObject) {
return forEachChild(
new NodeTreeAction<T>() {
@Override
public Object doAction(T node, Object... args) {
if(node.equals(searchObject)) {
return node;
}
else {
return null;
}
}
},
searchObject);
}
public void sort(final Comparator comparator) {
forEachChildList(
new SimpleNodeListTreeAction<T>() {
@Override
public void doAction(List node, Object... args) {
Collections.sort(node, comparator);
}
}, (Object) null);
}
public void sort() {
forEachChildList(
new SimpleNodeListTreeAction<T>() {
@Override
public void doAction(List node, Object... args) {
Collections.sort(node);
}
}, (Object) null);
}
}
public interface NodeTreeAction<T extends TreeNode> {
public Object doAction(T node, Object... args);
}
public interface SimpleNodeTreeAction<T extends TreeNode> {
public void doAction(T node, Object... args);
}
public interface NodeListTreeAction<T extends TreeNode> {
public Object doAction(List<T> node, Object... args);
}
public interface SimpleNodeListTreeAction<T extends TreeNode> {
public void doAction(List<T> node, Object... args);
}
谁能指出我如何使这个(假设不是完美的)解决方案变得更好(例如从方法返回实际类型对象,而不是现在的对象)。如果有人能提出更好的解决方案来解决这个问题,我也将不胜感激。
提前致谢...