sitinspring原创,转载请注明作者及出处.
树状结构是生活中常见的数据结构,如公司等级,军队等级,类别归属,标签结构都是树状结构的具体例子,如何将树状结构持久化和从持久化中取出对于使用关系型数据库的应用一直比较麻烦,不如DB4O这样的数据库直接存取这样简单.本人用XML文件模拟关系型数据库,实现了树状结构存入文件及从文件中取出的完整功能,对为树状结构存取头疼的程序员有一定参考价值.
例中使用的数据结构为标签结构,如Java包括J2EE和J2SE,J2EE包括JSp,EJB等,j2se包括swing,awt,applet等.
代码如下:
标签类,它能组成树状结构 :
 package com.sitinspring;
package com.sitinspring;

 import java.util.ArrayList;
import java.util.ArrayList;
 import java.util.List;
import java.util.List;


 /** *//**
/** *//**
 * 标签类
 * 标签类
 *
 * 
 * @author sitinspring
 * @author sitinspring
 *
 * 
 * @date 2007-12-19
 * @date 2007-12-19
 */
 */

 public class Tag
public class Tag  {
{
 // ID
    // ID
 private String id;
    private String id;

 // 父Tag的ID
    // 父Tag的ID
 private String parentId;
    private String parentId;

 // 标签名
    // 标签名
 private String name;
    private String name;

 // 其下的标签集合
    // 其下的标签集合
 private List<Tag> childTags;
    private List<Tag> childTags;

 // 父Tag
    // 父Tag
 private Tag parentTag;
    private Tag parentTag;
 
    
 // 四空格表示一个缩进
    // 四空格表示一个缩进
 private static final String TAB = "    ";
    private static final String TAB = "    ";


 /** *//**
    /** *//**
 * 构造函数
     * 构造函数
 *
     * 
 * @param name
     * @param name
 */
     */

 public Tag(String name)
    public Tag(String name)  {
{
 this.name = name;
        this.name = name;
 id = IdUtil.getId();
        id = IdUtil.getId();
 parentId = IdUtil.getDefaultId();
        parentId = IdUtil.getDefaultId();
 parentTag = null;
        parentTag = null;
 }
    }
 
    

 /** *//**
    /** *//**
 * 构造函数
     * 构造函数
 * @param id
     * @param id
 * @param parentId
     * @param parentId
 * @param name
     * @param name
 */
     */

 public Tag(String id,String parentId,String name)
    public Tag(String id,String parentId,String name) {
{
 this.id = id;
        this.id = id;
 this.parentId = parentId;
        this.parentId = parentId;
 this.name = name;
        this.name = name;
 
        
 parentTag = null;
        parentTag = null;
 }
    }


 /** *//**
    /** *//**
 * 添加一个Tag
     * 添加一个Tag
 */
     */

 public void add(Tag tag)
    public void add(Tag tag)  {
{

 if (childTags == null)
        if (childTags == null)  {
{
 childTags = new ArrayList<Tag>();
            childTags = new ArrayList<Tag>();
 }
        }

 // 设置被添加Tag的父ID和父Tag
        // 设置被添加Tag的父ID和父Tag
 tag.parentId = this.id;
        tag.parentId = this.id;
 tag.parentTag = this;
        tag.parentTag = this;

 // 将tag添加进链表
        // 将tag添加进链表
 childTags.add(tag);
        childTags.add(tag);
 }
    }


 /** *//**
    /** *//**
 * 从链表中删除一个Tag
     * 从链表中删除一个Tag
 */
     */

 public void remove(Tag tag)
    public void remove(Tag tag)  {
{

 if (childTags.contains(tag))
        if (childTags.contains(tag))  {
{
 // 重置被添加Tag的父ID和父Tag
            // 重置被添加Tag的父ID和父Tag
 tag.parentId = IdUtil.getDefaultId();
            tag.parentId = IdUtil.getDefaultId();
 tag.parentTag = null;
            tag.parentTag = null;

 // 将tag从链表中删除
            // 将tag从链表中删除
 childTags.remove(tag);
            childTags.remove(tag);
 }
        }
 }
    }
 
    

 public String toString()
    public String toString() {
{
 return " Tag名=" + name + " path=" + getPath()+ " id=" + id+ " parentId=" + parentId;
        return " Tag名=" + name + " path=" + getPath()+ " id=" + id+ " parentId=" + parentId;
 }
    }
 
    

 /** *//**
    /** *//**
 * 打印单位信息,包括其下包括的单位
     * 打印单位信息,包括其下包括的单位
 */
     */

 public void printInfo(String tabs)
    public void printInfo(String tabs)  {
{
 // 输出本身的信息
        // 输出本身的信息
 System.out.println(tabs + this.toString());
        System.out.println(tabs + this.toString());

 // 对链表进行检查
        // 对链表进行检查

 if (childTags == null)
        if (childTags == null)  {
{
 return;
            return;
 }
        }

 // 将链表的Tag集合中的Tag信息也打印出来
        // 将链表的Tag集合中的Tag信息也打印出来

 for (Tag tag : childTags)
        for (Tag tag : childTags)  {
{
 // tabs + TAB是让下到一层目录就缩进一次
            // tabs + TAB是让下到一层目录就缩进一次
 tag.printInfo(tabs + TAB);
            tag.printInfo(tabs + TAB);
 }
        }
 }
    }
 
 

 /** *//**
    /** *//**
 * 取得Tag的绝对路径
     * 取得Tag的绝对路径
 */
     */

 private String getPath()
    private String getPath()  {
{
 StringBuffer sb = new StringBuffer();
        StringBuffer sb = new StringBuffer();

 Tag tagPointer = parentTag;
        Tag tagPointer = parentTag;


 if (parentTag == null)
        if (parentTag == null)  {
{
 return "";
            return "";
 }
        }
 
        

 while (tagPointer != null)
        while (tagPointer != null)  {
{
 // 取得的单位名放置在前方
            // 取得的单位名放置在前方
 sb.insert(0, tagPointer.name + "/");
            sb.insert(0, tagPointer.name + "/");

 // 继续向上回溯
            // 继续向上回溯
 tagPointer = tagPointer.parentTag;
            tagPointer = tagPointer.parentTag;
 }
        }

 return sb.toString();
        return sb.toString();
 }
    }
 
    

 /** *//**
    /** *//**
 * 将一个Tag下的所有Tag全取出来,存放到allTags中
     * 将一个Tag下的所有Tag全取出来,存放到allTags中
 * @param allTags
     * @param allTags
 */
     */

 public void findAllTags(List<Tag> allTags)
    public void findAllTags(List<Tag> allTags) {
{
 allTags.add(this);
        allTags.add(this);
 
        
 // 对链表进行检查
        // 对链表进行检查

 if (childTags == null || childTags.size()==0)
        if (childTags == null || childTags.size()==0)  {
{
 return;
            return;
 }
        }

 // 将链表的Tag集合中的Tag信息也一起递归取出来
        // 将链表的Tag集合中的Tag信息也一起递归取出来

 for (Tag tagTmp : childTags)
        for (Tag tagTmp : childTags)  {
{
 tagTmp.findAllTags(allTags);
            tagTmp.findAllTags(allTags);
 }
        }
 }
    }


 public Tag getParentTag()
    public Tag getParentTag()  {
{
 return parentTag;
        return parentTag;
 }
    }


 public String getName()
    public String getName()  {
{
 return name;
        return name;
 }
    }


 public String getParentId()
    public String getParentId()  {
{
 return parentId;
        return parentId;
 }
    }


 public void setParentId(String parentId)
    public void setParentId(String parentId)  {
{
 this.parentId = parentId;
        this.parentId = parentId;
 }
    }


 public String getId()
    public String getId()  {
{
 return id;
        return id;
 }
    }


 public void setParentTag(Tag parentTag)
    public void setParentTag(Tag parentTag)  {
{
 this.parentTag = parentTag;
        this.parentTag = parentTag;
 }
    }
 }
}
制作ID的工具类:
 package com.sitinspring;
package com.sitinspring;


 /** *//**
/** *//**
 * 制作ID的工具类
 * 制作ID的工具类
 * @author sitinspring
 * @author sitinspring
 *
 *
 * @date 2007-12-19
 * @date 2007-12-19
 */
 */

 public final class IdUtil
public final class IdUtil {
{
 private static int index=1;
    private static int index=1;
 
    

 /** *//**
    /** *//**
 * 私有构造函数,防止生成实例
     * 私有构造函数,防止生成实例
 *
     *
 */
     */

 private IdUtil()
    private IdUtil() {
{
 
        
 }
    }
 
    

 /** *//**
    /** *//**
 * 用最简单的ID生成机制生成ID,仅为例子.
     * 用最简单的ID生成机制生成ID,仅为例子.
 * @return
     * @return
 */
     */

 public synchronized static String getId()
    public synchronized static String getId() {
{
 String retval=String.valueOf(index);
        String retval=String.valueOf(index);
 index++;
        index++;
 return retval;
        return retval;
 }
    }
 
    

 /** *//**
    /** *//**
 * 取得缺省ID
     * 取得缺省ID
 * @return
     * @return
 */
     */

 public static String getDefaultId()
    public static String getDefaultId() {
{
 return "0";
        return "0";
 }
    }
 }
}
将Tag从XML中读取存入的持久类:
 package com.sitinspring;
package com.sitinspring;

 import java.io.File;
import java.io.File;
 import java.io.FileWriter;
import java.io.FileWriter;
 import java.util.ArrayList;
import java.util.ArrayList;
 import java.util.Iterator;
import java.util.Iterator;
 import java.util.List;
import java.util.List;

 import org.dom4j.Document;
import org.dom4j.Document;
 import org.dom4j.DocumentHelper;
import org.dom4j.DocumentHelper;
 import org.dom4j.Element;
import org.dom4j.Element;
 import org.dom4j.io.OutputFormat;
import org.dom4j.io.OutputFormat;
 import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXReader;
 import org.dom4j.io.XMLWriter;
import org.dom4j.io.XMLWriter;


 /** *//**
/** *//**
 * 将Tag从XML中读取存入的持久类 春有百花秋有月 夏有凉风冬有雪 若无些事挂心头 便是人间好时节
 * 将Tag从XML中读取存入的持久类 春有百花秋有月 夏有凉风冬有雪 若无些事挂心头 便是人间好时节
 *
 * 
 * @author sitinspring
 * @author sitinspring
 *
 * 
 * @date 2007-12-19
 * @date 2007-12-19
 */
 */

 public class XmlPersistence
public class XmlPersistence  {
{
 // XML文件路径名
    // XML文件路径名
 private static final String xmlFile = "tags.xml";
    private static final String xmlFile = "tags.xml";


 /** *//**
    /** *//**
 * 将Tag存入XML文件
     * 将Tag存入XML文件
 *
     * 
 * @param tag
     * @param tag
 */
     */

 public void saveTag(Tag tag)
    public void saveTag(Tag tag)  {
{

 try
        try  {
{
 Document document = null;
            Document document = null;


 if ((new File(xmlFile).exists()))
            if ((new File(xmlFile).exists()))  {
{
 // 文件存在则读取document
                // 文件存在则读取document
 SAXReader reader = new SAXReader();
                SAXReader reader = new SAXReader();
 document = reader.read(new File(xmlFile));
                document = reader.read(new File(xmlFile));

 } else
            } else  {
{
 // 文件不存在则创建document
                // 文件不存在则创建document
 String text = "<tags></tags>";
                String text = "<tags></tags>";
 document = DocumentHelper.parseText(text);
                document = DocumentHelper.parseText(text);
 }
            }

 Element root = document.getRootElement();
            Element root = document.getRootElement();

 // 取出tag下的所有子Tag
            // 取出tag下的所有子Tag
 List<Tag> allTags = new ArrayList<Tag>();
            List<Tag> allTags = new ArrayList<Tag>();
 tag.findAllTags(allTags);
            tag.findAllTags(allTags);


 for (Tag tagTmp : allTags)
            for (Tag tagTmp : allTags)  {
{
 Element tagElm = root.addElement("tag");
                Element tagElm = root.addElement("tag");
 
                
 Element idElm=tagElm.addElement("id");
                Element idElm=tagElm.addElement("id");
 idElm.setText(tagTmp.getId());
                idElm.setText(tagTmp.getId());

 Element parentIdElm=tagElm.addElement("parentId");
                Element parentIdElm=tagElm.addElement("parentId");
 parentIdElm.setText(tagTmp.getParentId());
                parentIdElm.setText(tagTmp.getParentId());
 
                
 Element nameElm=tagElm.addElement("name");
                Element nameElm=tagElm.addElement("name");
 nameElm.setText(tagTmp.getName());
                nameElm.setText(tagTmp.getName());
 }
            }

 writeDocumentToFile(document);
            writeDocumentToFile(document);

 } catch (Exception ex)
        } catch (Exception ex)  {
{
 ex.printStackTrace();
            ex.printStackTrace();
 }
        }
 }
    }


 /** *//**
    /** *//**
 * 将Tag从XML文件中取出
     * 将Tag从XML文件中取出
 *
     * 
 * @param id
     * @param id
 */
     */

 public Tag fetchTagById(String id)
    public Tag fetchTagById(String id)  {
{

 try
        try  {
{
 Document document = null;
            Document document = null;


 if ((new File(xmlFile).exists()))
            if ((new File(xmlFile).exists()))  {
{
 // 文件存在则读取document
                // 文件存在则读取document
 SAXReader reader = new SAXReader();
                SAXReader reader = new SAXReader();
 document = reader.read(new File(xmlFile));
                document = reader.read(new File(xmlFile));

 } else
            } else  {
{
 // 文件不存在则返回空
                // 文件不存在则返回空
 return null;
                return null;
 }
            }

 // tag列表
            // tag列表
 List<Tag> tags=new ArrayList<Tag>();
            List<Tag> tags=new ArrayList<Tag>();
 
            
 // 遍历XML文档,取出元素放入tag列表
            // 遍历XML文档,取出元素放入tag列表
 Element root = document.getRootElement();
            Element root = document.getRootElement();            
 List tagElms=root.elements("tag");
            List tagElms=root.elements("tag");            

 for(Iterator it=tagElms.iterator();it.hasNext();)
            for(Iterator it=tagElms.iterator();it.hasNext();) {
{
 Element elm=(Element)it.next();
                Element elm=(Element)it.next();                
 Tag tag=new Tag(elm.elementText("id"),elm.elementText("parentId"),elm.elementText("name"));
                Tag tag=new Tag(elm.elementText("id"),elm.elementText("parentId"),elm.elementText("name"));                
 tags.add(tag);
                tags.add(tag);
 }
            }
 
            
 // 建立tag之间的级联关系
            // 建立tag之间的级联关系

 for(Tag tag:tags)
            for(Tag tag:tags) {
{
 setupTagRelationship(tag,tags);
                setupTagRelationship(tag,tags);
 }
            }
 
            
 // 找出tagID为输入参数的返回
            // 找出tagID为输入参数的返回

 for(Tag tag:tags)
            for(Tag tag:tags) {
{

 if(tag.getId().equals(id))
                if(tag.getId().equals(id)) {
{
 return tag;
                    return tag;
 }
                }
 }
            }

 } catch (Exception ex)
        } catch (Exception ex)  {
{
 ex.printStackTrace();
            ex.printStackTrace();
 }
        }

 return null;
        return null;
 }
    }
 
    

 /** *//**
    /** *//**
 * 建立tag之间的级联关系
     * 建立tag之间的级联关系
 * @param tag
     * @param tag
 * @param tags
     * @param tags
 */
     */

 private void setupTagRelationship(Tag tag,List<Tag> tags)
    private void setupTagRelationship(Tag tag,List<Tag> tags) {
{        

 for (Tag tagTmp : tags)
        for (Tag tagTmp : tags)  {
{

 if( tagTmp!=tag && tagTmp.getParentId().equals(tag.getId()))
            if( tagTmp!=tag && tagTmp.getParentId().equals(tag.getId())) {
{
 tag.add(tagTmp);
                tag.add(tagTmp);
 //tagTmp.setParentTag(tag);
                //tagTmp.setParentTag(tag);
 }
            }
 }
        }
 }
    }


 /** *//**
    /** *//**
 * 将Document写入文件
     * 将Document写入文件
 *
     * 
 * @param document
     * @param document
 */
     */

 private void writeDocumentToFile(Document document)
    private void writeDocumentToFile(Document document)  {
{

 try
        try  {
{
 OutputFormat format = OutputFormat.createPrettyPrint();
            OutputFormat format = OutputFormat.createPrettyPrint();
 format.setEncoding("GBK"); // 指定XML编码
            format.setEncoding("GBK"); // 指定XML编码

 XMLWriter writer = new XMLWriter(new FileWriter(xmlFile), format);
            XMLWriter writer = new XMLWriter(new FileWriter(xmlFile), format);
 writer.write(document);
            writer.write(document);
 writer.close();
            writer.close();

 } catch (Exception ex)
        } catch (Exception ex)  {
{
 ex.printStackTrace();
            ex.printStackTrace();
 }
        }
 }
    }
 }
}
测试代码:
 package com.sitinspring;
package com.sitinspring;


 /** *//**
/** *//**
 * 测试类
 * 测试类
 * @author sitinspring
 * @author sitinspring
 *
 *
 * @date 2007-12-19
 * @date 2007-12-19
 */
 */

 public class Main
public class Main {
{

 public static void main(String[] args)
    public static void main(String[] args) {
{
 // 建立Tag树
        // 建立Tag树
 Tag ejbTag=new Tag("EJB");
        Tag ejbTag=new Tag("EJB");
 Tag jspTag=new Tag("JSP");
        Tag jspTag=new Tag("JSP");        
 Tag j2eeTag=new Tag("J2EE");
        Tag j2eeTag=new Tag("J2EE");
 j2eeTag.add(ejbTag);
        j2eeTag.add(ejbTag);
 j2eeTag.add(jspTag);
        j2eeTag.add(jspTag);        
 
        
 Tag awtTag=new Tag("awt");
        Tag awtTag=new Tag("awt");
 Tag appletTag=new Tag("applet");
        Tag appletTag=new Tag("applet");    
 Tag swingTag=new Tag("swing");
        Tag swingTag=new Tag("swing");            
 Tag j2seTag=new Tag("J2SE");
        Tag j2seTag=new Tag("J2SE");
 j2seTag.add(awtTag);
        j2seTag.add(awtTag);
 j2seTag.add(appletTag);
        j2seTag.add(appletTag);
 j2seTag.add(swingTag);
        j2seTag.add(swingTag);
 
        
 Tag javaTag=new Tag("Java");
        Tag javaTag=new Tag("Java");
 javaTag.add(j2eeTag);
        javaTag.add(j2eeTag);
 javaTag.add(j2seTag);
        javaTag.add(j2seTag);
 
        
 System.out.println("打印建立好的根节点信息");
        System.out.println("打印建立好的根节点信息");
 javaTag.printInfo("");
        javaTag.printInfo("");
 
        
 // 将Tag树存入XML文件
        // 将Tag树存入XML文件
 XmlPersistence persistence=new XmlPersistence();
        XmlPersistence persistence=new XmlPersistence();
 persistence.saveTag(javaTag);
        persistence.saveTag(javaTag);
 
        
 // 取出tag树并打印信息
        // 取出tag树并打印信息
 String id=javaTag.getId();
        String id=javaTag.getId();        
 Tag tagFetched=persistence.fetchTagById(id);
        Tag tagFetched=persistence.fetchTagById(id);
 System.out.println("取出整颗树信息为");
        System.out.println("取出整颗树信息为");
 tagFetched.printInfo("");
        tagFetched.printInfo("");
 
        
 id=j2seTag.getId();
        id=j2seTag.getId();        
 System.out.println("取出部分树信息为");
        System.out.println("取出部分树信息为");
 persistence.fetchTagById(id).printInfo("");
        persistence.fetchTagById(id).printInfo("");
 }
    }
 }
}
测试结果:
 打印建立好的根节点信息
打印建立好的根节点信息
 Tag名=Java path= id=8 parentId=0
 Tag名=Java path= id=8 parentId=0
 Tag名=J2EE path=Java/ id=3 parentId=8
     Tag名=J2EE path=Java/ id=3 parentId=8
 Tag名=EJB path=Java/J2EE/ id=1 parentId=3
         Tag名=EJB path=Java/J2EE/ id=1 parentId=3
 Tag名=JSP path=Java/J2EE/ id=2 parentId=3
         Tag名=JSP path=Java/J2EE/ id=2 parentId=3
 Tag名=J2SE path=Java/ id=7 parentId=8
     Tag名=J2SE path=Java/ id=7 parentId=8
 Tag名=awt path=Java/J2SE/ id=4 parentId=7
         Tag名=awt path=Java/J2SE/ id=4 parentId=7
 Tag名=applet path=Java/J2SE/ id=5 parentId=7
         Tag名=applet path=Java/J2SE/ id=5 parentId=7
 Tag名=swing path=Java/J2SE/ id=6 parentId=7
         Tag名=swing path=Java/J2SE/ id=6 parentId=7
 取出整颗树信息为
取出整颗树信息为
 Tag名=Java path= id=8 parentId=0
 Tag名=Java path= id=8 parentId=0
 Tag名=J2EE path=Java/ id=3 parentId=8
     Tag名=J2EE path=Java/ id=3 parentId=8
 Tag名=EJB path=Java/J2EE/ id=1 parentId=3
         Tag名=EJB path=Java/J2EE/ id=1 parentId=3
 Tag名=JSP path=Java/J2EE/ id=2 parentId=3
         Tag名=JSP path=Java/J2EE/ id=2 parentId=3
 Tag名=J2SE path=Java/ id=7 parentId=8
     Tag名=J2SE path=Java/ id=7 parentId=8
 Tag名=awt path=Java/J2SE/ id=4 parentId=7
         Tag名=awt path=Java/J2SE/ id=4 parentId=7
 Tag名=applet path=Java/J2SE/ id=5 parentId=7
         Tag名=applet path=Java/J2SE/ id=5 parentId=7
 Tag名=swing path=Java/J2SE/ id=6 parentId=7
         Tag名=swing path=Java/J2SE/ id=6 parentId=7
 取出部分树信息为
取出部分树信息为
 Tag名=J2SE path=Java/ id=7 parentId=8
 Tag名=J2SE path=Java/ id=7 parentId=8
 Tag名=awt path=Java/J2SE/ id=4 parentId=7
     Tag名=awt path=Java/J2SE/ id=4 parentId=7
 Tag名=applet path=Java/J2SE/ id=5 parentId=7
     Tag名=applet path=Java/J2SE/ id=5 parentId=7
 Tag名=swing path=Java/J2SE/ id=6 parentId=7
     Tag名=swing path=Java/J2SE/ id=6 parentId=7

代码下载:
http://www.blogjava.net/Files/sitinspring/TagPersistenceSample.java20071219145515.rar