<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Pipboy</title>
    <description>Welcome to Pipboy's Reservation!&lt;br&gt;
亲爱的ChosenOne&lt;br&gt;
我知道你是一个除了好事,什么都敢做的人.&lt;br&gt;
但是在这里请放下手中的.233手枪.&lt;br&gt;
不要惹事,这里是交流和分享的地方.&lt;br&gt;
I will watch you!</description>
    <link>http://Pipboy.group.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>java csv文件解析</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/226518" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/226518</a>&nbsp;
          发表时间: 2008年08月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package xufei;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/*
 * 文件规则
 * Microsoft的格式是最简单的。以逗号分隔的值要么是“纯粹的”（仅仅包含在括号之前），
 * 要么是在双引号之间（这时数据中的双引号以一对双引号表示）。
 * Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K
 * 这一行包含七个字段（fields）：
 *	Ten Thousand
 *	10000
 *	 2710 
 *	空字段
 *	10,000
 *	It's "10 Grand", baby
 *	10K
 * 每条记录占一行
 * 以逗号为分隔符
 * 逗号前后的空格会被忽略
 * 字段中包含有逗号，该字段必须用双引号括起来。如果是全角的没有问题。
 * 字段中包含有换行符，该字段必须用双引号括起来
 * 字段前后包含有空格，该字段必须用双引号括起来
 * 字段中的双引号用两个双引号表示
 * 字段中如果有双引号，该字段必须用双引号括起来
 * 第一条记录，可以是字段名
 */
/** 

 * &lt;p>タイトル: xufei.CSVAnalysis.java&lt;/p>
 * &lt;p>説明: &lt;/p>
 * &lt;p>著作権: Copyright (c) 2006&lt;/p>
 * &lt;p>会社名: technodia&lt;/p>
 * @author	徐飞
 * @version 1.0
 * createDate Aug 11, 2008
 * 修正履歴
 * 修正日      修正者　　　　　　　修正理由
 */
public class CSVAnalysis {
	private InputStreamReader fr = null;
	private BufferedReader br = null;

	public CSVAnalysis(String f) throws IOException {
		fr = new InputStreamReader(new FileInputStream(f));
	}

	/**
	 * 解析csv文件 到一个list中
	 * 每个单元个为一个String类型记录，每一行为一个list。
	 * 再将所有的行放到一个总list中
	 * @return
	 * @throws IOException
	 */
	public List&lt;List&lt;String>> readCSVFile() throws IOException {
		br = new BufferedReader(fr);
		String rec = null;//一行
		String str;//一个单元格
		List&lt;List&lt;String>> listFile = new ArrayList&lt;List&lt;String>>();
		try {			
			//读取一行
			while ((rec = br.readLine()) != null) {
				Pattern pCells = Pattern
						.compile("(\"[^\"]*(\"{2})*[^\"]*\")*[^,]*,");
				Matcher mCells = pCells.matcher(rec);
				List&lt;String> cells = new ArrayList&lt;String>();//每行记录一个list
				//读取每个单元格
				while (mCells.find()) {
					str = mCells.group();
					str = str.replaceAll(
							"(?sm)\"?([^\"]*(\"{2})*[^\"]*)\"?.*,", "$1");
					str = str.replaceAll("(?sm)(\"(\"))", "$2");
					cells.add(str);
				}
				listFile.add(cells);
			}			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fr != null) {
				fr.close();
			}
			if (br != null) {
				br.close();
			}
		}
		return listFile;
	}

	public static void main(String[] args) throws Throwable {
		CSVAnalysis parser = new CSVAnalysis("c:/test2.csv");
		parser.readCSVFile();
	}
}


</pre><br /><br />从网上找到的一些信息， 再从新组织了一下。<br />处理异常部分没有写，应该根据不同的应用来写。
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/226518#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 11 Aug 2008 10:37:43 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/226518</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/226518</guid>
      </item>
      <item>
        <title>区间树</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/216224" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/216224</a>&nbsp;
          发表时间: 2008年07月18日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package acmcode;


/**
 * @author Leon.Chen
 *
 */
public class IntervalTree {


    /**
     * 红
     */
    private static final String RED = "red";

    /**
     * 黑
     */
    private static final String BLACK = "black";

    /**
     * 根节点
     */
    private RBNode root;

    /**
     * 左旋转
     * 
     * @param x
     */
    private void leftRotate(RBNode x) {
        RBNode y = x.right;
        x.right = y.left;
        y.left.parent = x;
        x.setMinPointAndMaxPoint();
        y.parent = x.parent;
        if (x.parent == null) {
            root = y;
        } else {
            if (x == x.parent.left) {
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
        }
        y.left = x;
        x.parent = y;
        y.setMinPointAndMaxPoint();
    }

    /**
     * 右旋转
     * 
     * @param y
     */
    private void rightRotate(RBNode y) {
        RBNode x = y.left;
        y.left = x.right;
        x.right.parent = y;
        y.setMinPointAndMaxPoint();
        x.parent = y.parent;
        if (y.parent == null) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        x.right = y;
        y.parent = x;
        x.setMinPointAndMaxPoint();
    }

    /**
     * 红黑树插入方法
     * 
     * @param z
     */
    public void RBInsert(RBNode z) {
        if (root == null) {
            root = z;
            root.color = BLACK;
            root.setMinPointAndMaxPoint(z);
        } else {
            RBNode x = root;
            RBNode y = null;
            while (isNotNilNode(x)) {
                y = x;
                x.setMinPointAndMaxPoint(z);
                if (z.value.compareTo(x.value) &lt; 0) {
                    x = x.left;
                } else {
                    x = x.right;
                }
            }
            if (z.value.compareTo(y.value) &lt; 0) {
                y.left = z;
            } else {
                y.right = z;
            }
            z.color = RED;
            z.setMinPointAndMaxPoint(z);
            z.parent = y;
        }
        z.left = new RBNode(BLACK);
        z.right = new RBNode(BLACK);
        RBInsertFixUp(z);
    }

    /**
     * 解决插入冲突
     * 
     * @param z
     */
    private void RBInsertFixUp(RBNode z) {
        while (z.parent != null && z.parent.color.equals(RED)) {
            if (z.parent == z.parent.parent.left) {
                RBNode y = z.parent.parent.right;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.right) {
                    z = z.parent;
                    leftRotate(z);
                } else if (z == z.parent.left) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    rightRotate(z.parent.parent);
                }
            } else {
                RBNode y = z.parent.parent.left;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.left) {
                    z = z.parent;
                    rightRotate(z);
                } else if (z == z.parent.right) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = BLACK;
    }

    /**
     * @param deleteNode
     */
    public void RBDelete(RBNode deleteNode) {
        RBNode y = null;
        RBNode z = serach(deleteNode.value);
        if (isNilNode(z.left) || isNilNode(z.right)) {
            y = z;
        } else {
            y = treeSuccessor(z);
        }
        RBNode x = null;
        if (isNotNilNode(y.left)) {
            x = y.left;
        } else {
            x = y.right;
        }
        x.parent = y.parent;
        if (isNilNode(y.parent)) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        if (y != z) {
            z.value = y.value;
        }
        if (y.color.equals(BLACK)) {
            RBDeleteFixUp(x);
        }
    }

    /**
     * @param x
     */
    private void RBDeleteFixUp(RBNode x) {
        // 解决黑黑冲突,完善中
        while (x != root && x.color.equals(BLACK)) {
            if (x == x.parent.left) {
                RBNode w = x.parent.right;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    leftRotate(x.parent);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.right.color.equals(BLACK)) {
                    w.left.color = BLACK;
                    w.color = RED;
                    rightRotate(w);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.right.color = BLACK;
                    leftRotate(x.parent);
                    x = root;
                }
            } else {
                RBNode w = x.parent.left;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    rightRotate(x.parent);
                    w = x.parent.left;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.left.color.equals(BLACK)) {
                    w.right.color = BLACK;
                    w.color = RED;
                    leftRotate(w);
                    w = x.parent.left;
                } else if (w.right.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.left.color = BLACK;
                    rightRotate(x.parent);
                    x = root;
                }
            }
        }
        x.color = BLACK;
    }

    /**
     * 找后继
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeSuccessor(RBNode node) {
        if (node.right != null) {
            return treeMiniMum(node.right);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.right) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 找前驱
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treePrecursor(RBNode node) {
        if (node.left != null) {
            return treeMaxiMum(node.left);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.left) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 最大节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMaxiMum(RBNode node) {
        while (isNotNilNode(node.right)) {
            node = node.right;
        }
        return node;
    }

    /**
     * 最小节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMiniMum(RBNode node) {
        while (isNotNilNode(node.left)) {
            node = node.left;
        }
        return node;
    }

    /**
     * 找节点的父节点
     * 
     * @param node
     * @return TreeNode
     */
    public RBNode getParentNode(RBNode node) {
        RBNode current = root;
        RBNode trailCurrent = null;
        while (isNotNilNode(current)) {
            if (current.value.compareTo(node.value) == 0) {
                break;
            }
            trailCurrent = current;
            if (node.value.compareTo(current.value) &lt; 0) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return trailCurrent;
    }

    /**
     * 搜索
     * 
     * @param value
     * @return TreeNode
     */
    public RBNode serach(RBValue value) {
        return treeSerach(root, value);
    }

    /**
     * 搜索
     * 
     * @param node
     * @param value
     * @return TreeNode
     */
    public RBNode treeSerach(RBNode node, RBValue value) {
        if (isNotNilNode(node) && node.value.compareTo(value) == 0) {
            return node;
        }
        if (value.compareTo(node.value) &lt; 0) {
            return treeSerach(node.left, value);
        } else {
            return treeSerach(node.right, value);
        }
    }

    /**
     * 中序遍历
     * 
     * @param node
     */
    public void inOrder(RBNode node) {
        if (isNotNilNode(node)) {
            inOrder(node.left);
            System.out.println(node.value+","+node.color);
            inOrder(node.right);
        }
    }
    
    /**
     * 先序遍历
     * 
     * @param node
     */
    public void perOrder(RBNode node) {
        if (isNotNilNode(node)) {
            System.out.println(node.value+","+node.color);
            perOrder(node.left);
            perOrder(node.right);
        }
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNotNilNode(RBNode node) {
        return node != null && node.value != null;
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNilNode(RBNode node) {
        return !isNotNilNode(node);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        IntervalTree tree = new IntervalTree();
        tree.RBInsert(new RBNode(new RBValue(0,3)));
        tree.RBInsert(new RBNode(new RBValue(5,8)));
        tree.RBInsert(new RBNode(new RBValue(6,10)));
        tree.RBInsert(new RBNode(new RBValue(8,9)));
        tree.RBInsert(new RBNode(new RBValue(15,23)));
        tree.RBInsert(new RBNode(new RBValue(16,21)));
        tree.RBInsert(new RBNode(new RBValue(17,19)));
        tree.RBInsert(new RBNode(new RBValue(19,20)));
        tree.RBInsert(new RBNode(new RBValue(25,30)));
        tree.RBInsert(new RBNode(new RBValue(26,26)));
        System.out.println("=================");
        System.out.println("root = "+tree.root.value);
        System.out.println("=================");
        tree.inOrder(tree.root);
        System.out.println("=================");
        tree.perOrder(tree.root);
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBNode {

    /**
     * 
     */
    public RBNode parent;

    /**
     * 
     */
    public RBNode left;

    /**
     * 
     */
    public RBNode right;

    /**
     * 
     */
    public RBValue value;

    /**
     * 
     */
    public String color;

    /**
     * @param color
     */
    public RBNode(String color) {
        this.color = color;
    }

    /**
     * 
     */
    public RBNode() {

    }

    /**
     * @param value
     */
    public RBNode(RBValue value) {
        this.value = value;
    }
    
    /**
     * @param node
     */
    public void setMinPointAndMaxPoint(RBNode node) {
        if(node.value.startPoint&lt;this.value.minPoint) {
            this.value.minPoint = node.value.startPoint;
        }
        if(node.value.endPoint>this.value.maxPoint) {
            this.value.maxPoint = node.value.endPoint;
        }
    }
    
    /**
     * 
     */
    public void setMinPointAndMaxPoint() {
        int min = 0;
        int max = 0;
        if (this.left.value == null && this.right.value == null) {
            min = this.value.startPoint;
            max = this.value.endPoint;
        } else {
            min = getMin();
            max = getMax();
        }
        this.value.minPoint = min;
        this.value.maxPoint = max;
    }
    
    /**
     * @return min
     */
    private int getMin() {
        RBNode left = this.left;
        RBNode right = this.right;
        int temp = getMin(left,right);
        if(this.value.startPoint > temp) {
            return temp;
        }
        return this.value.startPoint;
    }
    
    /**
     * @return max
     */
    private int getMax() {
        RBNode left = this.left;
        RBNode right = this.right;
        int temp = getMax(left,right);
        if(this.value.endPoint >temp) {
            return this.value.endPoint;
        }
        return temp;
    }
    
    /**
     * @param node1
     * @param node2
     * @return min
     */
    private int getMin(RBNode node1, RBNode node2) {
        if (node1.value == null && node2.value == null) {
            return 2147483647;
        }
        if (node1.value == null) {
            return node2.value.minPoint;
        }
        if (node2.value == null) {
            return node1.value.minPoint;
        }
        return (node1.value.minPoint &lt; node2.value.minPoint ? node1.value.minPoint : node2.value.minPoint);
    }
    
    /**
     * @param node1
     * @param node2
     * @return max
     */
    private int getMax(RBNode node1, RBNode node2) {
        if (node1.value == null && node2.value == null) {
            return 0;
        }
        if (node1.value == null) {
            return node2.value.maxPoint;
        }
        if (node2.value == null) {
            return node1.value.maxPoint;
        }
        return (node1.value.maxPoint &lt; node2.value.maxPoint ? node2.value.maxPoint : node1.value.maxPoint);
    }
}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBValue {

    /**
     * 
     */
    public int startPoint;

    /**
     * 
     */
    public int endPoint;

    /**
     * 初始化minPoint为无穷大
     */
    public int minPoint = 2147483647;

    /**
     * 
     */
    public int maxPoint;

    /**
     * @param startPoint
     * @param endPoint
     */
    public RBValue(int startPoint, int endPoint) {
        this.startPoint = startPoint;
        this.endPoint = endPoint;
    }

    /**
     * @param otherValue
     * @return 比较结果
     */
    public int compareTo(RBValue otherValue) {
        int thisVal = this.startPoint;
        int anotherVal = otherValue.startPoint;
        return (thisVal &lt; anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
    }

    public String toString() {
        return "[" + startPoint + "," + endPoint + "]" + " , [" + minPoint + "," + maxPoint + "]";
    }
}
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/216224#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 18 Jul 2008 15:47:41 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/216224</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/216224</guid>
      </item>
      <item>
        <title>红黑树初版</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/215494" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/215494</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package acmcode;

/**
 * Red-Black Tree
 * 
 * @author Leon.Chen
 */
public class RBTree {

    /**
     * 红
     */
    private static final String RED = "red";

    /**
     * 黑
     */
    private static final String BLACK = "black";

    /**
     * 根节点
     */
    private RBNode root;

    /**
     * 左旋转
     * 
     * @param x
     */
    private void leftRotate(RBNode x) {
        RBNode y = x.right;
        x.right = y.left;
        y.left.parent = x;
        y.parent = x.parent;
        if (x.parent == null) {
            root = y;
        } else {
            if (x == x.parent.left) {
                x.parent.left = y;
            } else {
                x.parent.right = y;
            }
        }
        y.left = x;
        x.parent = y;
    }

    /**
     * 右旋转
     * 
     * @param y
     */
    private void rightRotate(RBNode y) {
        RBNode x = y.left;
        y.left = x.right;
        x.right.parent = y;
        x.parent = y.parent;
        if (y.parent == null) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        x.right = y;
        y.parent = x;
    }

    /**
     * 红黑树插入方法
     * 
     * @param z
     */
    public void RBInsert(RBNode z) {
        if (root == null) {
            root = z;
            root.color = BLACK;
        } else {
            RBNode x = root;
            RBNode y = null;
            while (isNotNilNode(x)) {
                y = x;
                if (z.value.compareTo(x.value) &lt; 0) {
                    x = x.left;
                } else {
                    x = x.right;
                }
            }
            if (z.value.compareTo(y.value) &lt; 0) {
                y.left = z;
            } else {
                y.right = z;
            }
            z.color = RED;
            z.parent = y;
        }
        z.left = new RBNode(BLACK);
        z.right = new RBNode(BLACK);
        RBInsertFixUp(z);
    }

    /**
     * 解决插入冲突
     * 
     * @param z
     */
    private void RBInsertFixUp(RBNode z) {
        while (z.parent != null && z.parent.color.equals(RED)) {
            if (z.parent == z.parent.parent.left) {
                RBNode y = z.parent.parent.right;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.right) {
                    z = z.parent;
                    leftRotate(z);
                } else if (z == z.parent.left) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    rightRotate(z.parent.parent);
                }
            } else {
                RBNode y = z.parent.parent.left;
                if (y.color.equals(RED)) {
                    z.parent.color = BLACK;
                    y.color = BLACK;
                    z.parent.parent.color = RED;
                    z = z.parent.parent;
                } else if (z == z.parent.left) {
                    z = z.parent;
                    rightRotate(z);
                } else if (z == z.parent.right) {
                    z.parent.color = BLACK;
                    z.parent.parent.color = RED;
                    leftRotate(z.parent.parent);
                }
            }
        }
        root.color = BLACK;
    }

    /**
     * @param deleteNode
     */
    public void RBDelete(RBNode deleteNode) {
        RBNode y = null;
        RBNode z = serach(deleteNode.value);
        if (isNilNode(z.left) || isNilNode(z.right)) {
            y = z;
        } else {
            y = treeSuccessor(z);
        }
        RBNode x = null;
        if (isNotNilNode(y.left)) {
            x = y.left;
        } else {
            x = y.right;
        }
        x.parent = y.parent;
        if (isNilNode(y.parent)) {
            root = x;
        } else {
            if (y == y.parent.left) {
                y.parent.left = x;
            } else {
                y.parent.right = x;
            }
        }
        if (y != z) {
            z.value = y.value;
        }
        if (y.color.equals(BLACK)) {
            RBDeleteFixUp(x);
        }
    }

    /**
     * @param x
     */
    private void RBDeleteFixUp(RBNode x) {
        System.out.println("===="+x.value);
        // 解决黑黑冲突,完善中
        while (x != root && x.color.equals(BLACK)) {
            if (x == x.parent.left) {
                RBNode w = x.parent.right;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    leftRotate(x.parent);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.right.color.equals(BLACK)) {
                    w.left.color = BLACK;
                    w.color = RED;
                    rightRotate(w);
                    w = x.parent.right;
                } else if (w.left.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.right.color = BLACK;
                    leftRotate(x.parent);
                    x = root;
                }
            } else {
                RBNode w = x.parent.left;
                if (w.color.equals(RED)) {
                    w.color = BLACK;
                    x.parent.color = RED;
                    rightRotate(x.parent);
                    w = x.parent.left;
                } else if (w.left.color.equals(BLACK) && w.right.color.equals(BLACK)) {
                    w.color = RED;
                    x = x.parent;
                } else if (w.left.color.equals(BLACK)) {
                    w.right.color = BLACK;
                    w.color = RED;
                    leftRotate(w);
                    w = x.parent.left;
                } else if (w.right.color.equals(BLACK)) {
                    w.color = x.parent.color;
                    x.parent.color = BLACK;
                    w.left.color = BLACK;
                    rightRotate(x.parent);
                    x = root;
                }
            }
        }
        x.color = BLACK;
    }

    /**
     * 找后继
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeSuccessor(RBNode node) {
        if (node.right != null) {
            return treeMiniMum(node.right);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.right) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 找前驱
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treePrecursor(RBNode node) {
        if (node.left != null) {
            return treeMaxiMum(node.left);
        }
        RBNode currentNode = getParentNode(node);
        while (currentNode != null && node == currentNode.left) {
            node = currentNode;
            currentNode = getParentNode(node);
        }
        return currentNode;
    }

    /**
     * 最大节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMaxiMum(RBNode node) {
        while (isNotNilNode(node.right)) {
            node = node.right;
        }
        return node;
    }

    /**
     * 最小节点
     * 
     * @param node
     * @return RBNode
     */
    public RBNode treeMiniMum(RBNode node) {
        while (isNotNilNode(node.left)) {
            node = node.left;
        }
        return node;
    }

    /**
     * 找节点的父节点
     * 
     * @param node
     * @return TreeNode
     */
    public RBNode getParentNode(RBNode node) {
        RBNode current = root;
        RBNode trailCurrent = null;
        while (isNotNilNode(current)) {
            if (current.value.compareTo(node.value) == 0) {
                break;
            }
            trailCurrent = current;
            if (node.value.compareTo(current.value) &lt; 0) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return trailCurrent;
    }

    /**
     * 搜索
     * 
     * @param value
     * @return TreeNode
     */
    public RBNode serach(RBValue value) {
        return treeSerach(root, value);
    }

    /**
     * 搜索
     * 
     * @param node
     * @param value
     * @return TreeNode
     */
    public RBNode treeSerach(RBNode node, RBValue value) {
        if (isNotNilNode(node) && node.value.compareTo(value) == 0) {
            return node;
        }
        if (value.compareTo(node.value) &lt; 0) {
            return treeSerach(node.left, value);
        } else {
            return treeSerach(node.right, value);
        }
    }

    /**
     * 中序遍历
     * 
     * @param node
     */
    public void inOrder(RBNode node) {
        if (isNotNilNode(node)) {
            inOrder(node.left);
            System.out.println(node.value+","+node.color);
            inOrder(node.right);
        }
    }
    
    /**
     * 先序遍历
     * 
     * @param node
     */
    public void perOrder(RBNode node) {
        if (isNotNilNode(node)) {
            System.out.println(node.value+","+node.color);
            perOrder(node.left);
            perOrder(node.right);
        }
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNotNilNode(RBNode node) {
        return node != null && node.value != null;
    }

    /**
     * @param node
     * @return 是否为NIL[T]节点
     */
    private boolean isNilNode(RBNode node) {
        return !isNotNilNode(node);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        RBTree tree = new RBTree();
        
        
        tree.RBInsert(new RBNode(new RBValue(3)));
        tree.RBInsert(new RBNode(new RBValue(4)));
        tree.RBInsert(new RBNode(new RBValue(12)));
        tree.RBInsert(new RBNode(new RBValue(13)));
        tree.RBInsert(new RBNode(new RBValue(11)));
        tree.RBInsert(new RBNode(new RBValue(15)));
        tree.RBDelete(new RBNode(new RBValue(12)));
        System.out.println("=================");
        System.out.println("root = "+tree.root.value);
        System.out.println("=================");
        tree.inOrder(tree.root);
        System.out.println("=================");
        tree.perOrder(tree.root);
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

/**
 * @author Leon.Chen
 *
 */
public class RBNode {

    public RBNode parent;

    public RBNode left;

    public RBNode right;

    public RBValue value;

    public String color;

    public RBNode(String color) {
        this.color = color;
    }

    public RBNode() {

    }

    public RBNode(RBValue value) {
        this.value = value;
    }

}
</pre><br /><pre name="code" class="java">
package acmcode;

public class RBValue {

    public int value;

    public RBValue(int value) {
        this.value = value;
    }

    public int compareTo(RBValue otherValue) {
        int thisVal = this.value;
        int anotherVal = otherValue.value;
        return (thisVal &lt; anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
    }

    public String toString() {
        return new Integer(value).toString();
    }
}
</pre><br />忘了附图
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/215494#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Jul 2008 17:20:46 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/215494</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/215494</guid>
      </item>
      <item>
        <title>非 ajax级联下拉框</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/204214" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/204214</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <ol>
<li><span><span><span style="color: #ff0000;">以总公司, 分公司为例</span>&nbsp;&nbsp;&nbsp;</span></span></li>
<li><span class="number"><span style="color: #c00000;">1</span></span><span>.首先定义一个javascript对象&nbsp;用于存储你要级联的那些数据&nbsp;&nbsp;&nbsp;
<pre name="code" class="java">function subCompany(parentID, companyID, name) {   
    this.parentID = parentID; //总公司ID   
    this.companyID = companyID; //分公司ID  下拉框的value   
    this.name = name;           //分公司名   下拉框的text   
}</pre>
&nbsp;</span><span>&nbsp;</span><span>&nbsp;&nbsp;</span></li>
<li><span>&nbsp;&nbsp;</span></li>
<li><span class="number"><span style="color: #c00000;">2</span></span><span>.然后定义一个javascript&nbsp;数组来存放上面的对象&nbsp;&nbsp;
<pre name="code" class="java">var subCompanys = new Array();  </pre>
&nbsp;</span></li>
<li><span class="number"><span style="color: #c00000;">3</span></span><span>.接下来要将你从后台传来的数据&nbsp;放到数组里 &nbsp;&nbsp;</span></li>
<li><span>我这里是用jstl&nbsp;+ el
<pre name="code" class="java">这段代码要写在js标签里
&lt;c:forEach var="subCompany"  items="${formCommand.subCompanyCollection}"&gt;   
           subCompanys.push(new subCompany(
                  "&lt;c:out  value="${subCompany.parentID}"/&gt;", 
                  "&lt;c:out value="${subCompany.sid}" /&gt;",
                  "&lt;c:out value="${subCompany.name}" /&gt;"));   
&lt;/c:forEach&gt; </pre>
&nbsp;</span><span>&nbsp;</span></li>
<li>&nbsp;</li>
<li><span><span style="color: #ff6600;">4</span>. 再接下来 是当 总公司下拉框值变化时 触发的事件&nbsp;&nbsp;
<pre name="code" class="java">function companyChangeEdit(obj) {
    var parentID = obj.value;
    var subCompanySelect = obj.form.subCompany;// 显示分公司的下拉框

   subCompanySelect .options.length = 1;
    for(var i=0; i &lt; subCompanys.length; i++){
        var subCompanyObj = subCompanys[i];
        if(subCompanyObj.parentID == parentID){
            var oTempOption = document.createElement("option");
            oTempOption.text = subCompanyObj.name;
            oTempOption.value = subCompanyObj.companyID;
            subCompanySelect .options[subCompanySelect .options.length] 
                                = oTempOption;
        }
    }

   if(obj.form.parentCompany.selectedIndex == 0){ 
       obj.form.subCompanySelect .selectedIndex = 0;
		
    }
}</pre>
&nbsp;<br />&nbsp;&nbsp;</span></li>
<li><span>还有两个下拉框
<pre name="code" class="java">总公司的
&lt;select  name="parentCompany"
                onChange="companyChangeEdit(this);"&gt;
     &lt;option value="-1"&gt;
       请选择总公司 &lt;/option&gt;
     &lt;c:forEach var="company"
          items="${formCommand.companyCollection}"&gt;
           &lt;option value="&lt;c:out value="${company.sid}" /&gt;"
           &lt;c:if test="${company.sid == formCommand.companyId}"&gt;selected&lt;/c:if&gt;&gt;
            &lt;c:out value="${company.name}" /&gt;
           &lt;/option&gt;
      &lt;/c:forEach&gt;
&lt;/select&gt;
</pre>
&nbsp;&nbsp;&nbsp;
<pre name="code" class="java">分公司的
&lt;select  name="subCompany"&gt;

     &lt;option value="-1"&gt;
     请选择子公司
     &lt;/option&gt;
     &lt;c:forEach var="subCompany"
              items="${formCommand.currentSubCompanyCollection}"&gt;
             &lt;option value="&lt;c:out value="${subCompany.sid}" /&gt;"
             &lt;c:if test="${subCompany.sid == formCommand.subCompanyID}"&gt;selected&lt;/c:if&gt;&gt;
             &lt;c:out value="${subCompany.name}" /&gt;
             &lt;/option&gt;
     &lt;/c:forEach&gt;			
&lt;/select&gt;</pre>
&nbsp;</span></li>
</ol>
<p>&nbsp;嗯&nbsp; 就这些了 总的思想是把所有数据加载到页面上先, 然后在由javascript 来负责显示</p>
<p>没有用ajax&nbsp; 项目要求(经理的)</p>
<p>&nbsp;</p>
<p>还有一种方法是&nbsp;隐藏的iframe 我没有那么作&nbsp;因为还要写个页面 我觉得不爽<br />希望大家有什么好方法拿出来讨论啊&nbsp; 我就会这么多 还是个菜鸟啊&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/204214#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Jun 2008 16:43:12 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/204214</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/204214</guid>
      </item>
      <item>
        <title>java缩放图片</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/201752" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/201752</a>&nbsp;
          发表时间: 2008年06月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">

import java.awt.Image;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class ImgManager1 {

	public static void main(String args[]) {
		ImgManager1.reduceImgGif("c:/testgif.gif", "c:/xufnew/test02.gif", 150, 200);

	}

	/**
	 * 图像缩放 jpg格式
	 * 
	 * @param imgsrc
	 *            :原图片文件路径
	 * @param imgdist
	 *            :生成的缩略图片文件路径
	 * @param widthdist
	 *            :生成图片的宽度
	 * @param heightdist
	 *            :生成图片的高度
	 */
	public static void reduceImg(String imgsrc, String imgdist, int widthdist,
			int heightdist) {
		try {
			File srcfile = new File(imgsrc);
			if (!srcfile.exists()) {
				return;
			}
			Image src = ImageIO.read(srcfile);

			BufferedImage tag = new BufferedImage((int) widthdist,
					(int) heightdist, BufferedImage.TYPE_INT_RGB);
			/*
			 * Image.SCALE_SMOOTH 的缩略算法  生成缩略图片的平滑度的
			 * 优先级比速度高 生成的图片质量比较好 但速度慢
			 */
			tag.getGraphics().drawImage(
					src.getScaledInstance(widthdist, heightdist,
							Image.SCALE_SMOOTH), 0, 0, null);
			
			FileOutputStream out = new FileOutputStream(imgdist);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(tag);
			out.close();

		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	public static void reduceImgGif(String imgsrc, String imgdist, int widthdist,
			int heightdist) {
		try {
			File srcfile = new File(imgsrc);
			if (!srcfile.exists()) {
				return;
			}
			Image src = ImageIO.read(srcfile);

			BufferedImage tag = new BufferedImage((int) widthdist,
					(int) heightdist, BufferedImage.TYPE_INT_RGB);
			/*
			 * Image.SCALE_SMOOTH 的缩略算法  生成缩略图片的平滑度的
			 * 优先级比速度高 生成的图片质量比较好 但速度慢
			 */
			tag.getGraphics().drawImage(
					src.getScaledInstance(widthdist, heightdist,
							Image.SCALE_SMOOTH), 0, 0, null);
			
//			FileOutputStream out = new FileOutputStream(imgdist);
//			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
//			encoder.encode(tag);
//			out.close();
			ImageIO.write(tag, "gif", new File(imgdist));

		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * 根据图片路径 读取图片文件
	 * @param fileName
	 * @return
	 */
	public static BufferedImage readImage(String fileName) {
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(new File(fileName));
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return bi;
	}

	/**
	 * 生成新的图片文件
	 * @param im
	 * @param formatName
	 * @param fileName
	 * @return
	 */
	public static boolean writeImage(RenderedImage im, String formatName,
			String fileName) {
		boolean result = false;
		try {
			result = ImageIO.write(im, formatName, new File(fileName));
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return result;
	}

	/**
	 * 转换图片格式 到 jpg
	 * @param im
	 * @param fileName
	 * @return
	 */
	public static boolean writeJPEGImage(RenderedImage im, String fileName) {
		return writeImage(im, "JPEG", fileName);
	}

	/**
	 * 转换图片格式 到 gif  不知到好用不
	 * @param im
	 * @param fileName
	 * @return
	 */
	public static boolean writeGIFImage(RenderedImage im, String fileName) {
		return writeImage(im, "GIF", fileName);
	}

	public static boolean writePNGImage(RenderedImage im, String fileName) {
		return writeImage(im, "PNG", fileName);
	}

	public static boolean writeBMPImage(RenderedImage im, String fileName) {
		return writeImage(im, "BMP", fileName);
	}
}

</pre><br /><br /><br />从网上找到的一些代码  整理了一下 怕自己忘了 先放这<br /><br />我把一张1200 * 1600的jpg的图片 缩放到 150 * 200 文件大小由700多k 降到7k多点  清晰度还可以, 因为要把网站放到手机上, 所以要作,  按流量收费的. 呵呵<br /><br />由于gif编码是专利产品 所以java对他的支持不好, 有JPEGCodec 解码编码没有gif的<br /><br />有人说sun的 jimi 和 jai 可以 但我没有发现可以使用的方法
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/201752#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 10 Jun 2008 13:18:44 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/201752</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/201752</guid>
      </item>
      <item>
        <title>oracle 分页 </title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/194951" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/194951</a>&nbsp;
          发表时间: 2008年05月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
public String oraclePagination(int startRow, int rowsNumber, String filter){
		String sql = "";
		
		if(rowsNumber != Constants.DEFAULT_LONG) {
				
			sql = " SELECT * FROM  "
				+ " ( SELECT A.*, ROWNUM RN " 
				+ " FROM (" + filter + ") A " 
				+ " WHERE ROWNUM &lt;=  '" + (rowsNumber + startRow)+ "'"
				+ " )WHERE RN >=  '" + (startRow + 1) + "'" ;
		}
		return sql;
	}
</pre><br /><pre name="code" class="java">
    public void demo() {
        String sql = " select * from users ";
        int startRow = 0;//起始行号
        int rowsNumber = 10;//每页记录数
        sql = oraclePagination(startRow, rowsNumber, sql);
        //接下来该怎么作 就怎么作吧
    }
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/194951#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 20 May 2008 17:13:03 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/194951</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/194951</guid>
      </item>
      <item>
        <title>四则运算的中缀转后缀，逆波兰表达式求值</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/186104" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/186104</a>&nbsp;
          发表时间: 2008年04月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先描述问题<br /><pre name="code" class="java">
给定一个字符串
example:"4-(4-3*5+(2*4)+100)/10";
要求输出结果"-5.70";结果四舍五入，保留两位小数
</pre><br />首先进行的是括号优先级的处理<br /><pre name="code" class="java">
	public BigDecimal calculateString(String str) {
		char[] strs = str.toCharArray();
		Stack&lt;String> stack = new Stack&lt;String>();

		for (int i = 0; i &lt; strs.length; i++) {
			String stackStr = String.valueOf(strs[i]);
			stack.push(stackStr);
			if (")".equals(stack.top())) {
				String subStr = null;
				while (!"(".equals(stack.top())) {
					stack.pop();
					if (!"(".equals(stack.top())) {
						subStr = addEnd(subStr, stack.top());
					}
				}
				String pushStr = CalculateReversePolishExpression(subStr);
				stack.pop();
				stack.push(pushStr);
			}

		}
		String resultStr = null;
		while (stack.count != 0) {
			resultStr = CalculateReversePolishExpression(stack.toString());
		}
		BigDecimal result = null;
		if (resultStr != null) {
			result = new BigDecimal(resultStr);
		} else {
			result = BigDecimal.ZERO;
		}
		return result.setScale(2, BigDecimal.ROUND_HALF_UP);
	}
</pre><br />将每个字符逐一进栈，当扫描到")"时，进行出栈操作，直到栈顶元素等于"("<br />并记录出栈的"("与")"之间的字符串为subStr<br />然后是对subStr求后缀表达式，并计算结果<br />也就是这句代码<br /><pre name="code" class="java">
String pushStr = CalculateReversePolishExpression(subStr);
</pre><br />再把结果进栈<br />最后stack的内容是去掉括号的一个四则表达式<br />再进行一次CalculateReversePolishExpression方法，则得到最终结果<br /><br />中缀转后缀表达式的基本思路<br />基本思路如下：<br />用一个链表 List&lt;String> 储存将要生成的后缀表达式<br />用一个栈 Stack&lt;String> 储存操作符<br />判断当前节点， 如果是操作数， 直接加入后缀表达式中， 如果是操作符，则比较前一个操作符和当前操作符的优先级，<br />如果前一个操作符优先级较高，则将前一个操作符加入后缀表达式中，否则将操作符压入操作符栈，如果遇到反括号 ')', 则在操作符栈中反向搜索，直到遇到匹配的正括号为止，将中间的操作符依次加到后缀表达式中。<br /><br />然后是后缀表达式的计算<br /><br />遍历储存后缀表达式的链表，将元素依次进栈，当遇到操作符时，连续出栈两个元素，进行运算，再将结果进栈，最后栈内留下的元素就是计算结果<br /><br />最后再贴出茫茫多的代码<br /><pre name="code" class="java">
package graph;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * 应用：逆波兰表达式
 * 
 * @author Leon.Chen
 * 
 */
public class CalculateString {

	public BigDecimal calculateString(String str) {
		char[] strs = str.toCharArray();
		Stack&lt;String> stack = new Stack&lt;String>();

		for (int i = 0; i &lt; strs.length; i++) {
			String stackStr = String.valueOf(strs[i]);
			stack.push(stackStr);
			if (")".equals(stack.top())) {
				String subStr = null;
				while (!"(".equals(stack.top())) {
					stack.pop();
					if (!"(".equals(stack.top())) {
						subStr = addEnd(subStr, stack.top());
					}
				}
				String pushStr = CalculateReversePolishExpression(subStr);
				stack.pop();
				stack.push(pushStr);
			}

		}
		String resultStr = null;
		while (stack.count != 0) {
			resultStr = CalculateReversePolishExpression(stack.toString());
		}
		BigDecimal result = null;
		if (resultStr != null) {
			result = new BigDecimal(resultStr);
		} else {
			result = BigDecimal.ZERO;
		}
		return result.setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	public String[] matcher(String regex, String str) {
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(str);
		List&lt;String> list = new ArrayList&lt;String>();
		while (matcher.find()) {
			list.add(matcher.group());
		}
		String[] result = new String[list.size()];
		return list.toArray(result);
	}

	public List&lt;String> createReversePolishExpression(String subStr) {
		String regex = "\\d+\\.{0,1}\\d*";
		String[] numbers = matcher(regex, subStr);
		String changeStr = subStr.replaceAll(regex, "0").replaceAll("\\-\\-0",
				"-1").replaceAll("\\+\\-0", "+1").replaceAll("\\*\\-0", "*1")
				.replaceAll("\\/\\-0", "/1");
		char[] chars = changeStr.toCharArray();
		int index = 0;
		List&lt;String> list = new ArrayList&lt;String>();
		for (int i = 0; i &lt; chars.length; i++) {
			String str = String.valueOf(chars[i]);
			if ("0".equals(str)) {
				list.add(numbers[index++]);
			} else if ("1".equals(str)) {
				list.add("-" + numbers[index++]);
			} else {
				list.add(str);
			}
		}
		List&lt;String> suffix = new ArrayList&lt;String>();
		Stack&lt;String> operator = new Stack&lt;String>();
		for (int i = 0; i &lt; list.size(); i++) {
			if (!isOperatorType(list.get(i))) {
				suffix.add(list.get(i));
			} else {
				if (operator.count == 0) {
					operator.push(list.get(i));
				} else {
					while (operator.count != 0&&compare(operator.top(), list.get(i)) >= 0) {
						String top = operator.top();
						operator.pop();
						suffix.add(top);
					} 
					operator.push(list.get(i));

				}
			}
		}

		while (operator.count != 0) {
			suffix.add(operator.top());
			operator.pop();
		}
		return suffix;
	}

	public String CalculateReversePolishExpression(String subStr) {
		List&lt;String> suffix = createReversePolishExpression(subStr);
		Stack&lt;Double> stack = new Stack&lt;Double>();
		for (int i = 0; i &lt; suffix.size(); i++) {
			if (!isOperatorType(suffix.get(i))) {
				stack.push(Double.valueOf(suffix.get(i)));
			} else {
				Double current = stack.top();
				stack.pop();
				Double previous = null;
				if (stack.count != 0) {
					previous = stack.top();
					stack.pop();
				} else {
					previous = new Double(0);
				}
				Double result = calculate(suffix.get(i), previous, current);
				stack.push(result);
			}
		}
		return stack.top().toString();
	}

	public String addEnd(String str, String a) {
		StringBuffer buf = new StringBuffer();
		buf.append(a);
		if (str != null) {
			buf.append(str);
		}
		return buf.toString();
	}

	public boolean isOperatorType(String str) {
		if (str.equals("+") || str.equals("-") || str.equals("*")
				|| str.equals("/")) {
			return true;
		}
		return false;
	}

	public int compare(String op1, String op2) {
		Integer iop1 = getOperator(op1);
		Integer iop2 = getOperator(op2);
		return iop1.compareTo(iop2);
	}

	public Integer getOperator(String op) {
		if ("+".equals(op) || "-".equals(op)) {
			return new Integer(0);
		}
		if ("*".equals(op) || "/".equals(op)) {
			return new Integer(1);
		}
		return null;
	}

	public Double calculate(String op, Double previous, Double current) {
		if ("+".equals(op)) {
			return previous + current;
		}
		if ("-".equals(op)) {
			return previous - current;
		}
		if ("*".equals(op)) {
			return previous * current;
		}
		if ("/".equals(op)) {
			return previous / current;
		}
		return null;
	}

	public static void main(String[] args) {
		String[] strs = new String[]{"(5+6)*7","(-1)/(-3)","1/(-3)","-1/7","7+(3*5)-(8+20/2)","4-(4-3*5+(2*4)+100)/10"};
		for(int i=0;i&lt;strs.length;i++){
			BigDecimal result = new CalculateString().calculateString(strs[i]);
			System.out.println(result.toString());
		}
		
	}

}

</pre><br />自己写的stack<br /><br /><pre name="code" class="java">
package graph;

public class Stack&lt;T> {
	public StackNode&lt;T> stackTop;
	public int count;
	public void push(T info) {
		StackNode&lt;T> node = new StackNode&lt;T>();
		node.info = info;
		node.link = stackTop;
		stackTop = node;
		count++;
	} 
	
	public void pop() {
		if(stackTop == null) {
			System.out.println("null stack");
		} else {
			stackTop = stackTop.link;
			count--;
		}

	}
	
	public boolean isEmpty() {
		return count == 0;
	}
	
	public T top() {
		if(stackTop == null) {
			return null;
		}
		return stackTop.info;
	}
	
	public String toString(){
		Stack&lt;T> other = new Stack&lt;T>();
		while(count != 0){
			T top = top();
			pop();
			other.push(top);
		}
		StringBuffer buf = new StringBuffer();
		while(other.count !=0){
			buf.append(other.top());
			other.pop();
		}
		return buf.toString();
	}

}

</pre><br />stack节点<br /><pre name="code" class="java">
package graph;

public class StackNode&lt;T> {
	public StackNode&lt;T> link;
	public T info;
}

</pre><br /><br />懒得copy的话下载附件
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/186104#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 23 Apr 2008 23:10:37 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/186104</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/186104</guid>
      </item>
      <item>
        <title>最大0，1子矩阵</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/184635" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/184635</a>&nbsp;
          发表时间: 2008年04月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          首先描述一下问题<br /><pre name="code" class="java">
 /**
 * 
 * 时间限制(普通/Java):6000MS/20000MS 运行内存限制:65536KByte
 * 总提交:131 测试通过:32
 * 描述
 * 在一个0,1方阵中找出其中最大的全0子矩阵，所谓最大是指O的个数最多
 * 输入
 * 单组数据第一行为整数N，其中1&lt;=N&lt;=2000，为方阵的大小，紧接着N行每行均有N个0或1，相邻两数间严格用一个空格隔开
 * 输出
 * 输出仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数
 * 样例输入
 * 5
 * 0 1 0 1 0
 * 0 0 0 0 0
 * 0 0 0 0 1
 * 1 0 0 0 0
 * 0 1 0 0 0
 * 样例输出
 * 9
 */
</pre><br />我的做法是遍历每个点，根据每个点横向和纵向的构造全0矩阵，选取最大的全0矩阵输出<br />正确性应该是没问题的，不过时间复杂度<br />遍历的复杂度是o(n^2)然后每个点构造矩形复杂度也是o(n^2)<br />最大时间复杂度就为n^4<br />因此求优化<img src="/images/smiles/icon_arrow.gif"/><br /><pre name="code" class="java">
package graph;
/**
 * 
 * 时间限制(普通/Java):6000MS/20000MS 运行内存限制:65536KByte
 * 总提交:131 测试通过:32
 * 描述
 * 在一个0,1方阵中找出其中最大的全0子矩阵，所谓最大是指O的个数最多
 * 输入
 * 单组数据第一行为整数N，其中1&lt;=N&lt;=2000，为方阵的大小，紧接着N行每行均有N个0或1，相邻两数间严格用一个空格隔开
 * 输出
 * 输出仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数
 * 样例输入
 * 5
 * 0 1 0 1 0
 * 0 0 0 0 0
 * 0 0 0 0 1
 * 1 0 0 0 0
 * 0 1 0 0 0
 * 样例输出
 * 9
 * 
 * @author Leon.Chen
 *
 */
public class AllZeroMatrix {
	/**
	 * 输入矩阵
	 */
	public int[][] matrix;
	/**
	 * 矩阵最大行
	 */
	public int maxRow;
	/**
	 * 矩阵最大列
	 */
	public int maxColumn;
	/**
	 * 被乘数
	 */
	public int multiplicand;
	/**
	 * 最大全零矩阵
	 */
	public int totalCount;

	/**
	 * 每个点向下，向右扩张矩形，取最大的矩形
	 * 
	 * @param row
	 * @param column
	 */
	public void spread(int row, int column) {
		int rowStart = row;
		int rowEnd = row;
		while (rowEnd &lt; maxRow) {
			if (matrix[rowEnd][column] == 0) {
				rowEnd++;
			} else {
				break;
			}
		}
		this.multiplicand = 0;
		spreadMatrixRight(rowStart, rowEnd, column);
		int count = (rowEnd - rowStart) * multiplicand;
		if (totalCount &lt; count) {
			totalCount = count;
		}
		int columnStart = column;
		int columnEnd = column;
		while (columnEnd &lt; maxColumn) {
			if (matrix[row][columnEnd] == 0) {
				columnEnd++;
			} else {
				break;
			}
		}
		this.multiplicand = 0;
		spreadMatrixbelow(columnStart, columnEnd, row);
		count = (columnEnd - columnStart) * multiplicand;
		if (totalCount &lt; count) {
			totalCount = count;
		}
	}

	/**
	 * 矩阵的向右扩张
	 * 
	 * @param start
	 * @param end
	 * @param column
	 */

	public void spreadMatrixRight(int start, int end, int column) {
		boolean flg = true;
		for (int i = start; i &lt; end; i++) {
			if (matrix[i][column] == 1) {
				flg = false;
				break;
			}
		}
		if (flg) {
			multiplicand++;
			int nextColumn = column;
			nextColumn++;
			if (nextColumn &lt; maxColumn) {
				spreadMatrixRight(start, end, nextColumn);
			}
		}
	}

	/**
	 * 矩阵的向下扩张
	 * 
	 * @param start
	 * @param end
	 * @param row
	 */
	public void spreadMatrixbelow(int start, int end, int row) {
		boolean flg = true;
		for (int i = start; i &lt; end; i++) {
			if (matrix[row][i] == 1) {
				flg = false;
				break;
			}
		}
		if (flg) {
			multiplicand++;
			int nextRow = row;
			nextRow++;
			if (nextRow &lt; maxRow) {
				spreadMatrixbelow(start, end, nextRow);
			}
		}
	}

	/**
	 * 得到最大全零矩阵的大小
	 * 
	 * @param printMatrix
	 */
	public void getAllZeroMatrix(int[][] printMatrix) {
		matrix = printMatrix;
		maxRow = matrix.length;
		maxColumn = matrix[0].length;
		for (int i = 0; i &lt; maxRow; i++) {
			for (int j = 0; j &lt; maxColumn; j++) {
				int count = (maxRow - i) * (maxColumn - j);
				if (count &lt;= totalCount) {
					continue;
				}
				if (matrix[i][j] != 1) {
					spread(i, j);
				}
			}
		}
		System.out.println(totalCount);
	}
	
	public static void main(String[] args) {
		int[][] printMatrix = new int[][]{
				{0,1,0,1,0},
				{0,0,0,0,0},
				{0,0,0,0,1},
				{1,0,0,0,0},
				{0,1,0,0,0},
		};
		long start = System.currentTimeMillis();
		new AllZeroMatrix().getAllZeroMatrix(printMatrix);
		long end = System.currentTimeMillis();
		System.out.println((end-start)+"ms");
	}
}

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/184635#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 20 Apr 2008 21:16:47 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/184635</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/184635</guid>
      </item>
      <item>
        <title>hibernate 分页</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/183784" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/183784</a>&nbsp;
          发表时间: 2008年04月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
 &lt;s:url id="url_pre" value="show.action">
         &lt;s:param name="pageNow" value="pageNow-1">&lt;/s:param>
     &lt;/s:url>
     &lt;s:url id="url_next" value="show.action">
         &lt;s:param name="pageNow" value="pageNow+1">&lt;/s:param>
     &lt;/s:url>  
     &lt;s:a href="%{url_pre}">上一页&lt;/s:a>
     
     &lt;s:iterator value="students" status="status">
        &lt;s:url id="url" value="show.action">
            &lt;s:param name="pageNow" value="pageNow"/>
        &lt;/s:url>
     &lt;/s:iterator>
     &lt;s:a href="%{url_next}">下一页&lt;/s:a> 

</pre><br /><br />hibernate 条件查询<br /><pre name="code" class="java">
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.gt("age", new Integer(20)));
criteria.add(Restrictions.lt("age", new Integer(40)));
List users = criteria.list();
</pre><br /><br />逻辑or<br /><pre name="code" class="java">
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.or( 
                   Restrictions.eq("age", new Integer(20)), 
                   Restrictions.isNull("age") 
               )); 
List users = criteria.list();

</pre><br /><br />like<br /><pre name="code" class="java">
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));
List users = criteria.list();
</pre><br /><br />begin<br /><pre name="code" class="java">
Criteria criteria = session.createCriteria(User.class);
Integer[] ages = {new Integer(20), new Integer(40)};
Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};
criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));
List users = criteria.list();

</pre><br /><br />DetachedCriteria 使用<br />1<br /><pre name="code" class="java">
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class).createCriteria("customers");
beautyCriteria.add(Restrictions.eq("name", "Gates"));
</pre><br /><br />2<br /><pre name="code" class="java">
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class).createAlias("customers", "c");
beautyCriteria.add(Restrictions.eq("c.name", "Gates"));
</pre><br /><br />综合<br /><pre name="code" class="java">
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class, "b").;
DetachedCriteria customerCriteria = beautyCriteria.createAlias("customers", c");
beautyCriteria.add(Restrictions.le("b.age", new Long(20)));
customerCriteria.add(Restrictions.eq("c.name", "Gates"));
</pre><br /><br />javaeye<br /><pre name="code" class="java">
public PaginationSupport findPageByCriteria(final DetachedCriteria detachedCriteria, final int pageSize,    
            final int startIndex) {    
        return (PaginationSupport) getHibernateTemplate().execute(new HibernateCallback() {    
            public Object doInHibernate(Session session) throws HibernateException {    
                Criteria criteria = chedCriteria.getExecutableCriteria(session);    
                int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();    
                criteria.setProjection(null);    
                List items = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();    
                PaginationSupport ps = new PaginationSupport(items, totalCount, pageSize, startIndex);    
                return ps;    
            }    
        }, true);    
    } 
这个有问题搞出来的是一个数组 多表查询的化
</pre><br /><br />http://www.javaeye.com/topic/14657?page=1
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/183784#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 Apr 2008 15:47:08 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/183784</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/183784</guid>
      </item>
      <item>
        <title>数据挖掘 决策树ID3算法原理</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/181958" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/181958</a>&nbsp;
          发表时间: 2008年04月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          上一篇博客写了ID3算法的简单实现<br />这一篇讲讲ID3的原理<br />写这个算法是由于某同事的同学的毕业设计，关系够复杂的了==|||，写完这个算法，突然对数据挖掘有了兴趣，决定把C4.5,C5.0算法也一并实现，并且再研究一下数据挖掘的分类算法<br />其实这篇原理，没有我自己的内容。。。引用某人blog的东东吧（我本人倒是很反感抄袭的）<br />首先奉上blog作者：神威异度<br />虽然未曾与之交谈，不过经历千辛万苦的搜索之后，终于在他的blog发现了有价值的东西（这里要提一下，想要在国内搜索出有价值的东西真不容易，到处充斥着转载，小小鄙视一下我自己先），在这里万分感谢神威异度同学<br />奉上blog链接：http://www.blog.edu.cn/user2/huangbo929/archives/2006/1533249.shtml<br />再不厌其烦的把人家的东西copy到我这里。<br /><br />决策树生成原理<br />Abstract <br />This paper details the ID3 classification algorithm. Very simply, ID3 builds a decision tree from a fixed set of examples. The resulting tree is used to classify future samples. The example has several attributes and belongs to a class (like yes or no). The leaf nodes of the decision tree contain the class name whereas a non-leaf node is a decision node. The decision node is an attribute test with each branch (to another decision tree) being a possible value of the attribute. ID3 uses information gain to help it decide which attribute goes into a decision node. The advantage of learning a decision tree is that a program, rather than a knowledge engineer, elicits knowledge from an expert.<br /><br />Introduction <br />J. Ross Quinlan originally developed ID3 at the University of Sydney. He first presented ID3 in 1975 in a book, Machine Learning, vol. 1, no. 1. ID3 is based off the Concept Learning System (CLS) algorithm. The basic CLS algorithm over a set of training instances C:<br /><br />Step 1: If all instances in C are positive, then create YES node and halt.<br /><br />If all instances in C are negative, create a NO node and halt.<br /><br />Otherwise select a feature, F with values v1, ..., vn and create a decision node.<br /><br />Step 2: Partition the training instances in C into subsets C1, C2, ..., Cn according to the values of V.<br /><br />Step 3: apply the algorithm recursively to each of the sets Ci.<br /><br />Note, the trainer (the expert) decides which feature to select.<br /><br />ID3 improves on CLS by adding a feature selection heuristic. ID3 searches through the attributes of the training instances and extracts the attribute that best separates the given examples. If the attribute perfectly classifies the training sets then ID3 stops; otherwise it recursively operates on the n (where n = number of possible values of an attribute) partitioned subsets to get their "best" attribute. The algorithm uses a greedy search, that is, it picks the best attribute and never looks back to reconsider earlier choices.<br /><br />Discussion <br />ID3 is a nonincremental algorithm, meaning it derives its classes from a fixed set of training instances. An incremental algorithm revises the current concept definition, if necessary, with a new sample. The classes created by ID3 are inductive, that is, given a small set of training instances, the specific classes created by ID3 are expected to work for all future instances. The distribution of the unknowns must be the same as the test cases. Induction classes cannot be proven to work in every case since they may classify an infinite number of instances. Note that ID3 (or any inductive algorithm) may misclassify data.<br /><br />Data Description <br /> <br /><br />The sample data used by ID3 has certain requirements, which are:<br /><br />Attribute-value description - the same attributes must describe each example and have a fixed number of values. <br />Predefined classes - an example's attributes must already be defined, that is, they are not learned by ID3. <br />Discrete classes - classes must be sharply delineated. Continuous classes broken up into vague categories such as a metal being "hard, quite hard, flexible, soft, quite soft" are suspect. <br />Sufficient examples - since inductive generalization is used (i.e. not provable) there must be enough test cases to distinguish valid patterns from chance occurrences. <br />Attribute Selection <br /> <br /><br />How does ID3 decide which attribute is the best? A statistical property, called information gain, is used. Gain measures how well a given attribute separates training examples into targeted classes. The one with the highest information (information being the most useful for classification) is selected. In order to define gain, we first borrow an idea from information theory called entropy. Entropy measures the amount of information in an attribute. <br /><br />Given a collection S of c outcomes<br /><br /> <br /><br />Entropy(S) = S -p(I) log2 p(I) <br /> <br /><br />where p(I) is the proportion of S belonging to class I. S is over c. Log2 is log base 2.<br /><br />Note that S is not an attribute but the entire sample set.<br /><br />Example 1 <br /> <br /><br />If S is a collection of 14 examples with 9 YES and 5 NO examples then<br /><br /> <br /><br />Entropy(S) = - (9/14) Log2 (9/14) - (5/14) Log2 (5/14) = 0.940 <br /> <br /><br />Notice entropy is 0 if all members of S belong to the same class (the data is perfectly classified). The range of entropy is 0 ("perfectly classified") to 1 ("totally random").<br /><br />Gain(S, A) is information gain of example set S on attribute A is defined as<br /><br /> <br /><br />Gain(S, A) = Entropy(S) - S ((|Sv| / |S|) * Entropy(Sv)) <br /> <br /><br />Where:<br /><br />S is each value v of all possible values of attribute A<br /><br />Sv = subset of S for which attribute A has value v<br /><br />|Sv| = number of elements in Sv <br /><br />|S| = number of elements in S<br /><br />Example 2 <br /> <br /><br />Suppose S is a set of 14 examples in which one of the attributes is wind speed. The values of Wind can be Weak or Strong. The classification of these 14 examples are 9 YES and 5 NO. For attribute Wind, suppose there are 8 occurrences of Wind = Weak and 6 occurrences of Wind = Strong. For Wind = Weak, 6 of the examples are YES and 2 are NO. For Wind = Strong, 3 are YES and 3 are NO. Therefore<br /><br /> <br /><br />Gain(S,Wind)=Entropy(S)-(8/14)*Entropy(Sweak)-(6/14)*Entropy(Sstrong) <br /> <br /><br />= 0.940 - (8/14)*0.811 - (6/14)*1.00 <br /><br />= 0.048 <br /><br />Entropy(Sweak) = - (6/8)*log2(6/8) - (2/8)*log2(2/8) = 0.811<br /><br />Entropy(Sstrong) = - (3/6)*log2(3/6) - (3/6)*log2(3/6) = 1.00<br /><br />For each attribute, the gain is calculated and the highest gain is used in the decision node.<br /><br />Example of ID3 <br /> <br /><br />Suppose we want ID3 to decide whether the weather is amenable to playing baseball. Over the course of 2 weeks, data is collected to help ID3 build a decision tree (see table 1).<br /><br />The target classification is "should we play baseball?" which can be yes or no.<br /><br />The weather attributes are outlook, temperature, humidity, and wind speed. They can have the following values:<br /><br />outlook = { sunny, overcast, rain }<br /><br />temperature = {hot, mild, cool }<br /><br />humidity = { high, normal }<br /><br />wind = {weak, strong }<br /><br />Examples of set S are:<br /><br />Day Outlook Temperature Humidity Wind Play ball <br />D1 Sunny  Hot High  Weak No  <br />D2 Sunny  Hot High  Strong No  <br />D3 Overcast  Hot High  Weak Yes  <br />D4 Rain  Mild High  Weak Yes  <br />D5 Rain  Cool Normal  Weak Yes  <br />D6 Rain  Cool Normal  Strong No  <br />D7 Overcast  Cool Normal  Strong Yes  <br />D8 Sunny  Mild High  Weak No  <br />D9 Sunny  Cool Normal  Weak Yes  <br />D10 Rain  Mild Normal  Weak Yes  <br />D11 Sunny  Mild Normal  Strong Yes  <br />D12 Overcast  Mild High  Strong Yes  <br />D13 Overcast  Hot Normal  Weak Yes  <br />D14 Rain  Mild High  Strong No  <br /><br /><br /><br /> <br /><br />Table 1 <br /> <br /><br />We need to find which attribute will be the root node in our decision tree. The gain is calculated for all four attributes:<br /><br />Gain(S, Outlook) = 0.246<br /><br />Gain(S, Temperature) = 0.029<br /><br />Gain(S, Humidity) = 0.151<br /><br />Gain(S, Wind) = 0.048 (calculated in example 2)<br /><br />Outlook attribute has the highest gain, therefore it is used as the decision attribute in the root node.<br /><br />Since Outlook has three possible values, the root node has three branches (sunny, overcast, rain). The next question is "what attribute should be tested at the Sunny branch node?" Since we=92ve used Outlook at the root, we only decide on the remaining three attributes: Humidity, Temperature, or Wind.<br /><br />Ssunny = {D1, D2, D8, D9, D11} = 5 examples from table 1 with outlook = sunny<br /><br />Gain(Ssunny, Humidity) = 0.970<br /><br />Gain(Ssunny, Temperature) = 0.570<br /><br />Gain(Ssunny, Wind) = 0.019<br /><br />Humidity has the highest gain; therefore, it is used as the decision node. This process goes on until all data is classified perfectly or we run out of attributes.<br /><br />The final decision = tree<br /><br />The decision tree can also be expressed in rule format:<br /><br />IF outlook = sunny AND humidity = high THEN playball = no<br /><br />IF outlook = rain AND humidity = high THEN playball = no<br /><br />IF outlook = rain AND wind = strong THEN playball = yes<br /><br />IF outlook = overcast THEN playball = yes<br /><br />IF outlook = rain AND wind = weak THEN playball = yes<br /><br />ID3 has been incorporated in a number of commercial rule-induction packages. Some specific applications include medical diagnosis, credit risk assessment of loan applications, equipment malfunctions by their cause, classification of soybean diseases, and web search classification.<br /><br />Conclusion <br />The discussion and examples given show that ID3 is easy to use. Its primary use is replacing the expert who would normally build a classification tree by hand. As industry has shown, ID3 has been effective.
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/181958#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 11 Apr 2008 22:24:36 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/181958</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/181958</guid>
      </item>
      <item>
        <title>决策树ID3算法</title>
        <author>leon_a</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://leon-a.javaeye.com">leon_a</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/178585" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/178585</a>&nbsp;
          发表时间: 2008年04月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
package graph;      
     
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;      
     
/**      
 * 决策树的ID3算法      
 * 参照实现http://www.blog.edu.cn/user2/huangbo929/archives/2006/1533249.shtml    
 * @author Leon.Chen      
 */     
public class DTree {      
          
    /**    
     * root    
     */     
    TreeNode root;      
          
    /**    
     * 可见性数组    
     */     
    private static boolean[] visable;      
          
    private Object[] array;  
    
    private int index;
     
    /**    
     * @param args    
     */     
    @SuppressWarnings("boxing")      
    public static void main(String[] args) {      
        //初始数据      
        Object[] array = new Object[] {       
                        new String[]{ "Sunny"    ,"Hot"   ,"High"    ,"Weak"    ,"No" },      
                        new String[]{ "Sunny"    ,"Hot"   ,"High"    ,"Strong"  ,"No" },      
                        new String[]{ "Overcast" ,"Hot"   ,"High"    ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"High"    ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Cool"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Cool"  ,"Normal"  ,"Strong"  ,"No" },      
                        new String[]{ "Overcast" ,"Cool"  ,"Normal"  ,"Strong"  ,"Yes"},      
                        new String[]{ "Sunny"    ,"Mild"  ,"High"    ,"Weak"    ,"No" },      
                        new String[]{ "Sunny"    ,"Cool"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Sunny"    ,"Mild"  ,"Normal"  ,"Strong"  ,"Yes"},      
                        new String[]{ "Overcast" ,"Mild"  ,"High"    ,"Strong"  ,"Yes"},      
                        new String[]{ "Overcast" ,"Hot"   ,"Normal"  ,"Weak"    ,"Yes"},      
                        new String[]{ "Rain"     ,"Mild"  ,"High"    ,"Strong"  ,"No" },      
                        };      
              
        DTree tree = new DTree();       
        tree.create(array,4);
    } 
    
    public void create(Object[] array,int index){
    	this.array = array;
    	init(array,index);
    	createDTree(array);
    	printDTree(root);
    }
       
    public Object[] getMaxGain(Object[] array){   
        Object[] result = new Object[2];   
        double gain = 0;   
        int index = 0;
        
        for(int i=0;i&lt;visable.length;i++){   
            if(!visable[i]){   
                double value = gain(array,i);   
                if(gain &lt; value){   
                    gain = value;   
                    index = i;   
                }   
            }   
        }   
        result[0] = gain;   
        result[1] = index;   
        visable[index] = true;   
        return result;   
    }   
       
    public void createDTree(Object[] array) {   
        Object[] maxgain = getMaxGain(array);   
        if (root == null) {   
            root = new TreeNode();   
            root.parent = null;   
            root.parentArrtibute = null;   
            root.arrtibutes = getArrtibutes(((Integer) maxgain[1]).intValue());   
            root.nodeName = getNodeName(((Integer) maxgain[1]).intValue());  
            root.childNodes = new TreeNode[root.arrtibutes.length];
            insertTree(array,root);
        }
    }   
       
    public void insertTree(Object[] array,TreeNode parentNode){
    	String[] arrtibutes = parentNode.arrtibutes;
    	for(int i=0;i&lt;arrtibutes.length;i++){
    		Object[] pickArray = pickUpAndCreateArray(array,arrtibutes[i],getNodeIndex(parentNode.nodeName));
    		Object[] info = getMaxGain(pickArray);
    		double gain = ((Double)info[0]).doubleValue();
    		if(gain != 0){
    			int index = ((Integer) info[1]).intValue();
    			System.out.println("gain = "+gain+" ,node name = "+getNodeName(index));
        		TreeNode currentNode = new TreeNode();
        		currentNode.parent = parentNode;
        		currentNode.parentArrtibute = arrtibutes[i];
        		currentNode.arrtibutes = getArrtibutes(index);
        		currentNode.nodeName = getNodeName(index);
        		currentNode.childNodes = new TreeNode[currentNode.arrtibutes.length];
        		parentNode.childNodes[i] = currentNode;
        		insertTree(pickArray,currentNode);
    		}else {
    			TreeNode leafNode = new TreeNode();
    			leafNode.parent = parentNode;
    			leafNode.parentArrtibute = arrtibutes[i];
    			leafNode.arrtibutes = new String[0];
    			leafNode.nodeName = getLeafNodeName(pickArray);
    			leafNode.childNodes = new TreeNode[0];
    			parentNode.childNodes[i] = leafNode;
    		}
    	}

    }
    
    public void printDTree(TreeNode node){
    	System.out.println(node.nodeName);

    	TreeNode[] childs = node.childNodes;
    	for(int i=0;i&lt;childs.length;i++){
    		if(childs[i]!=null){
    			System.out.println(childs[i].parentArrtibute);
    			printDTree(childs[i]);
    		}
    	}
    }
  
    /**      
     * @param dataArray 原始数组 D     
     * @param criterion 标准值      
     * @return double      
     */     
    public void init(Object[] dataArray,int index) {
    	this.index = index;
        //数据初始化   
        visable = new boolean[((String[])dataArray[0]).length];      
        for(int i=0;i&lt;visable.length;i++) {    
            if(i == index){   
                visable[i] = true;    
            }else {   
                visable[i] = false;    
            }   
        }   
    }   
    
    public Object[] pickUpAndCreateArray(Object[] array,String arrtibute,int index){
    	List&lt;String[]> list = new ArrayList&lt;String[]>();
    	for(int i=0;i&lt;array.length;i++){
    		String[] strs = (String[])array[i];
    		if(strs[index].equals(arrtibute)){
    			list.add(strs);
    		}
    	}
    	return list.toArray();
    }
  
    /**    
     * Entropy(S)    
     * @param array    
     * @return double     
     */     
    public double gain(Object[] array,int index) {      
        String[] playBalls = getArrtibutes(this.index);   
        int[] counts = new int[playBalls.length];      
        for(int i=0;i&lt;counts.length;i++) {   
            counts[i] = 0;      
        }   
        for(int i=0;i&lt;array.length;i++) {   
            String[] strs = (String[])array[i];   
            for(int j=0;j&lt;playBalls.length;j++) {   
                if(strs[this.index].equals(playBalls[j])) {   
                    counts[j]++;   
                }   
            }   
        }   
        /**  
         * Entropy(S) = S -p(I) log2 p(I)  
         */  
        double entropyS = 0;   
        for(int i=0;i&lt;counts.length;i++) {      
            entropyS += DTreeUtil.sigma(counts[i],array.length);      
        }   
        String[] arrtibutes = getArrtibutes(index);   
        /**  
         * total ((|Sv| / |S|) * Entropy(Sv))   
         */  
        double sv_total = 0;   
        for(int i=0;i&lt;arrtibutes.length;i++){   
            sv_total += entropySv(array, index,arrtibutes[i],array.length);   
        }   
        return entropyS-sv_total;   
    }   
       
    /**  
     * ((|Sv| / |S|) * Entropy(Sv))  
     * @param array  
     * @param index  
     * @param arrtibute  
     * @param allTotal  
     * @return  
     */  
    public double entropySv(Object[] array,int index,String arrtibute,int allTotal) {   
        String[] playBalls = getArrtibutes(this.index);   
        int[] counts = new int[playBalls.length];   
        for(int i=0;i&lt;counts.length;i++) {   
            counts[i] = 0;      
        }   
  
        for (int i = 0; i &lt; array.length; i++) {   
            String[] strs = (String[]) array[i];   
            if (strs[index].equals(arrtibute)) {   
                for (int k = 0; k &lt; playBalls.length; k++) {   
                    if (strs[this.index].equals(playBalls[k])) {   
                        counts[k]++;   
                    }   
                }   
            }   
        }   
  
        int total = 0;   
        double entropySv = 0;    
        for(int i=0;i&lt;counts.length;i++){   
            total += counts[i];   
        }   
        for(int i=0;i&lt;counts.length;i++){   
            entropySv += DTreeUtil.sigma(counts[i],total);    
        }    
        return DTreeUtil.getPi(total, allTotal)*entropySv;   
    }   
          
    @SuppressWarnings("unchecked")   
    public String[] getArrtibutes(int index) {      
        TreeSet&lt;String> set = new TreeSet&lt;String>(new SequenceComparator());      
        for (int i = 0; i &lt; array.length; i++) {      
            String[] strs = (String[]) array[i];      
            set.add(strs[index]);      
        }      
        String[] result = new String[set.size()];      
        return set.toArray(result);      
    }   
          
    public String getNodeName(int index) {    
    	String[] strs = new String[]{"Outlook","Temperature","Humidity","Wind","Play ball"};
    	for(int i=0;i&lt;strs.length;i++){
    		if(i == index){
    			return strs[i];
    		}
    	}
    	return null;    
    }
    
    public String getLeafNodeName(Object[] array){
    	if(array!=null && array.length>0){
    		String[] strs = (String[])array[0];
    		return strs[index];
    	}
    	return null;		
    }
    
    public int getNodeIndex(String name) {  
    	String[] strs = new String[]{"Outlook","Temperature","Humidity","Wind","Play ball"};
    	for(int i=0;i&lt;strs.length;i++){
    		if(name.equals(strs[i])){
    			return i;
    		}
    	}
        return -1;    
    } 
}      

package graph;      
     
/**    
 * @author B.Chen    
 */     
public class TreeNode {      
     
    /**    
     * 父    
     */     
    TreeNode parent;    
     
    /**    
     * 指向父的哪个属性    
     */     
    String parentArrtibute;      
     
    /**    
     * 节点名    
     */     
    String nodeName;      
     
    /**    
     * 属性数组    
     */     
    String[] arrtibutes;    
    
    /**
     * 节点数组
     */
    TreeNode[] childNodes;

}      

package graph;   
  
public class DTreeUtil {   
  
    /**  
     * 属性值熵的计算 Info(T)=(i=1...k)pi*log（2）pi  
     *   
     * @param x  
     * @param total  
     * @return double  
     */  
    public static double sigma(int x, int total) {
    	if(x == 0){
    		return 0;
    	}
        double x_pi = getPi(x, total);   
        return -(x_pi * logYBase2(x_pi));   
    }   
  
    /**  
     * log2y  
     *   
     * @param y  
     * @return double  
     */  
    public static double logYBase2(double y) {   
        return Math.log(y) / Math.log(2);   
    }   
  
    /**  
     * pi是当前这个属性出现的概率（=出现次数/总数）  
     *   
     * @param x  
     * @param total  
     * @return double  
     */  
    public static double getPi(int x, int total) {   
        return x * Double.parseDouble("1.0") / total;   
    }  

}   

package graph;

import java.util.Comparator;

public class SequenceComparator implements Comparator {

    public int compare(Object o1, Object o2) throws ClassCastException {
        String str1 = (String) o1;
        String str2 = (String) o2;
        return str1.compareTo(str2);
    }

}

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/178585#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Apr 2008 22:18:50 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/178585</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/178585</guid>
      </item>
      <item>
        <title>stuts2 国际化 乱码问题</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/178033" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/178033</a>&nbsp;
          发表时间: 2008年03月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          转载 <a href="http://www.blogjava.net/max/archive/2006/11/01/78536.html" target="_blank">http://www.blogjava.net/max/archive/2006/11/01/78536.html</a><br />国际化是商业系统中不可或缺的一部分，所以无论您学习的是什么Web框架，它都是必须掌握的技能。 <br /><br />其实，Struts 1.x在此部分已经做得相当不错了。它极大地简化了我们程序员在做国际化时所需的工作，例如，如果您要输出一条国际化的信息，只需在代码包中加入FILE-NAME_xx_XX.properties（其中FILE-NAME为默认资源文件的文件名），然后在struts-config.xml中指明其路径，再在页面用标志输出即可。 <br /><br />不过，所谓&ldquo;没有最好，只有更好&rdquo;。Struts 2.0并没有在这部分止步，而是在原有的简单易用的基础上，将其做得更灵活、更强大。 <br /><br />国际化Hello World <br />下面让我们看一个例子&mdash;&mdash;HelloWorld。这个例子演示如何根据用户浏览器的设置输出相应的HelloWorld。 <br /><br />在Eclipse创建工程配置开发和运行环境（如果对这个步骤有问题，可以参考我早前的文章《为Struts 2.0做好准备》）。 <br /><br />在src文件夹中加入struts.properties文件，内容如下： <br />struts.custom.i18n.resources=globalMessages <br />Struts 2.0有两个配置文件，struts.xml和struts.properties都是放在WEB-INF/classes/下。 <br />struts.xml用于应用程序相关的配置 <br />struts.properties用于Struts 2.0的运行时（Runtime）的配置 <br /><br /><br />在src文件夹中加入globalMessages_en_US.properties文件，内容如下： <br /><pre name="code" class="java">HelloWorld=Hello World!</pre> <br />在src文件夹中加入globalMessages_zh_CN.properties文件，内容如下： <br /><pre name="code" class="java">HelloWorld=你好，世界！</pre><br /> 在此想和大家分享一个不错的编写properties文件的Eclipse插件（plugin），有了它我们在编辑一些简体中文、繁体中文等Unicode文本时，就不必再使用native2ascii编码了。您可以通过Eclipse中的软件升级（Software Update）安装此插件，步骤如下： <br /><br /><pre name="code" class="java">1、展开Eclipse的Help菜单，将鼠标移到Software Update子项，在出现的子菜单中点击Find and Install；
2、在Install/Update对话框中选择Search for new features to install，点击Next；
3、在Install对话框中点击New Remote Site；
4、在New Update Site对话框的Name填入&ldquo;PropEdit&rdquo;或其它任意非空字符串，在URL中填入http://propedit.sourceforge.jp/eclipse/updates/；
5、在Site to include to search列表中，除上一步加入的site外的其它选项去掉，点击Finsih；
6、在弹出的Updates对话框中的Select the features to install列表中将所有结尾为&ldquo;3.1.x&rdquo;的选项去掉（适用于Eclipse 3.2版本的朋友）；
7、点击Finish关闭对话框；
8、在下载后，同意安装，再按提示重启Eclipse，在工具条看到形似vi的按钮表示安装成功，插件可用。此时，Eclpise中所有properties文件的文件名前有绿色的P的图标作为标识。  </pre>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/178033#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 31 Mar 2008 14:06:06 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/178033</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/178033</guid>
      </item>
      <item>
        <title>按装oracle后 eclips提示jvm版本太低的问题</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/171262" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/171262</a>&nbsp;
          发表时间: 2008年03月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天在自己的机器上安装了 oracle9i <br />再启动eclipse的时候，提示JVM版本太低，安装oracle前是没有任何问题的，而且，这台机器上装的JDK也够高了，1.5。。猜测问题应该处在环境变量的设置上，于是重新设置了一下环境变量的CLASSPATH ，竟然不好使，晕了，查了一下，原来问题不出在CLASSPATH 上，而出在PATH上，在PATH的变量值中，有一个是oracle用到的jre1.3，所以系统在查找环境变量中的jre的值时首先找到的是这个，从而引起错误。。<br /><br />问题具体描述：点击eclipse.exe提示:Version 1.3.1_01 of the JVM is not suitable for this product. Version:1.4.1 or greater is required.<br /><br />解决方法：将一个高版本的JDK中的jre的路径设置在那个底版本jre的前面.<br /><br />oracle11g的jvm是1.5的所以没有问题
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/171262#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 14 Mar 2008 11:03:37 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/171262</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/171262</guid>
      </item>
      <item>
        <title>oracle卸载</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/171260" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/171260</a>&nbsp;
          发表时间: 2008年03月14日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在win2000企业版操作系统下，卸载Oracle 9i ： <br />    1、停止所有Oracle服务<br /><br />    2、删除注册表中的所有关于Oracle项<br /><br />    （1）在HKEY_LOCAL_MACHINE\SOFTWARE下，删除Oracle目录<br /><br />    （2）在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services下，删除所有Oracle项<br /><br />    （3）在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services下，删除所有Oracle项<br /><br />    （4）在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下，删除所有Oracle项<br /><br />    （5）在HKEY_CLASSES_ROOT下，删除所有Oracle项<br /><br />    3、删除硬盘上所有Oracle文件<br /><br />    （1）Oracle安装文件<br /><br />    （2）系统目录下，在Program files文件夹中的Oracle文件<br /><br />    4、重启，完成卸载。在win2000企业版操作系统下，卸载Oracle 9i ： <br />    1、停止所有Oracle服务<br /><br />    2、删除注册表中的所有关于Oracle项<br /><br />    （1）在HKEY_LOCAL_MACHINE\SOFTWARE下，删除Oracle目录<br /><br />    （2）在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services下，删除所有Oracle项<br /><br />    （3）在HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services下，删除所有Oracle项<br /><br />    （4）在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下，删除所有Oracle项<br /><br />    （5）在HKEY_CLASSES_ROOT下，删除所有Oracle项<br /><br />    3、删除硬盘上所有Oracle文件<br /><br />    （1）Oracle安装文件<br /><br />    （2）系统目录下，在Program files文件夹中的Oracle文件<br /><br />    4、重启，完成卸载。
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/171260#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 14 Mar 2008 11:00:18 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/171260</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/171260</guid>
      </item>
      <item>
        <title>设计模式学习小结</title>
        <author>Joard</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://joard.javaeye.com">Joard</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/168069" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/168069</a>&nbsp;
          发表时间: 2008年03月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这段时间重新翻看了一下阎宏的《Java与模式》，把里面我敢兴趣的地方摘抄与此。<br />首先<br /><div class="quote_title">Gof 写道</div><div class="quote_div">本书中的<span style="color: #ff0000"><strong>设计模式</strong></span>是<span style="color: #3366ff">对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。</span></div><br /><br /><span style="font-size: small"><strong>一.面向对象软件设计的核心问题：可维护性(Maintainability)与可复用性(Reuseability)。</strong></span><br /><br /><span style="font-size: small"><strong>二.维护性较差的原因：</strong></span><br />过于僵硬 Rigidity   &lt;---> 可扩展性 Extensibility<br />过于脆弱 Fragility  &lt;---> 灵活性   Flexibility<br />复用率低 Immobility<br />粘度过高 Viscosity  &lt;---> 可插入性 Pluggability<br /><br /><span style="font-size: small"><strong>三.面向对象设计的几个原则</strong></span><br />开-闭原则         Open-Closed Principle              OCP<br />里氏代换原则      Liskov Substitution Principle      LSP<br />依赖倒转原则      Dependency Inversion Principle     DIP<br />接口隔离原则      Interface Segregation Principle    ISP<br />组合/聚合复用原则 Composition/Aggregation Principle  CARP<br />迪米特法则        Law of Demeter                     LoD<br />可扩展性：OCP, LSP, DIP,CARP<br />灵活性：OCP, ISP,LoD<br />以上两点的交集就是&ldquo;可维护性复用&rdquo;。<br /><br /><span style="font-size: small"><strong>1.开闭原则 OCP</strong></span><br />一个软件的实体应当对扩展开放，对修改关闭。<br />Software entities should be open for extension,but closed for modification.<br /><br />对可变性的封装原则 Principle of Encapsulation of Variation   EVP<br />EVP实际上是设计模式的<span style="color: #ff0000">主题</span>，换言之，所有的设计模式都是对不同的可变性的封装，从而使系统在不同的角度上达到OCP要求。<br /><br /><span style="font-size: small"><strong>2.里氏代换原则 LSP</strong></span><br />如果对每一个类型为T1的对象o1，都有类型为T2的对象o2，使得以T1定义的所有程序P在所有对象o1都代换成o2时，程序P的<span style="color: #ff0000">行为没有变化</span>，那么类型T2是T1的子类型。<br />LSP要求凡是基类使用的地方，子类型一定适用。<br /><span style="color: #3366ff">LSP是一条非常严格的原则，要求基类变为子类的时候，其程序行为不发生改变。在oop时并没有严格按照LSP来做。</span><br /><br /><span style="font-size: small"><strong>3.依赖倒转原则 DIP</strong></span><br />表述1：抽象不应当依赖于细节，细节应当依赖于抽象。<br />       Abstractions should not depend upon details, details should depend upon abstractions.<br />表述2：要针对接口编程，不要针对实现编程。<br />       Program to an interface, not an implementation.<br /><br /><span style="font-size: small"><strong>4.接口隔离原则 ISP</strong></span><br />使用多个专门的接口比使用单一的总接口要好。<br />一个类对另一个类的依赖性应当是建立在最小接口上的(LoD)。<br /><br /><span style="font-size: small"><strong>5.合成/聚合复用原则 CARP</strong></span><br />= 合成复用原则 Composite Reuse Principle CRP<br />要尽量使用合成/聚合，尽量不要使用继承。<br />继承的优点：①新类易实现. ②易修改或扩展<br />      缺点：①继承复用破环包装，白箱复用.<br />            ②超类发生变化，子类不得不改变.<br />            ③继承的实现是静态的，不能在运行时改变.<br /><span style="color: #3366ff">优缺点的②是相互对应的。<br /></span><br /><span style="font-size: small"><strong>6.迪米特法则 LoD</strong></span><br />= 最少知识原则 Least Konwledge Principle<br />一个对象应当对其他对象有尽可能少的了解。<br />表述：<br />①只与你直接的朋友们通信 Only talk to your immediate friends<br />②不要跟陌生人说话 Don's talk to strangers<br />③每一个软件单位对其他的单位都只有最少的知识，而且局限于那些与本单位密切相关的软件单位。<br />LoD的<span style="color: #ff0000">实质</span>是控制对象之间的信息流量，流向及信息的影响。<br />①优先考虑将一个类设置成不变类.<br />②尽量降低类/成员的访问权限.<br /><br />要想恰到好处地在一个系统里面使用设计模式，必须做到以下几点：<br />①完全了解面临的问题，这就是说要完全了解具体情况。如果不完全了解所面临的难题，怎么能谈得上解决问题呢？<br />②完全了解模式，这就是说要十分懂得理论。如果不完全懂得所使用的理论，怎么能够正确地应用这一理论呢？<br />③非常了解怎样使用设计模式解决实际的问题，这就是说要将模式理论与具体系统需求情况相结合。如果设计师不知道一个设计模式怎样对系统设计有帮组的话，最好不要使用这个模式。不要只是因为想在简历上写上设计模式方面的经验就盲目地使用模式。<br /><br />来看看gof是怎么说的<br /><div class="quote_title">Gof 写道</div><div class="quote_div">通常你通过引入额外的间接层获得灵活性和可变性的同时，你也使设计变得更复杂并/或牺牲了一定的性能。一个设计模式只有当它提供的灵活性是真正需要的时候，才有必要使用。</div><br /><br /><span style="font-size: small"><strong>写在最后</strong></span><br />原本想写个总结什么的，写写各种模式的设计，再举个简单例子什么的。最后大感不必（神啊！原谅我的懒惰吧！）在这次翻看设计模式时，最大的感受是&ldquo;万变不离其中&rdquo;。很多设计模式在设计时都遵循上面列举的几个<span style="color: #3366ff">原则</span>，不同的模式对原则有不同的侧重，在学习时可以运用这些原则去分析这些既有的设计模式，判断它们的优缺点。进而提高自己的分析和设计能力，毕竟GOF的23种设计模式也有它的局限，总会有新的问题待自己去解决。再说设计模式本身也不是语言中立的，先不提OOP与FP，就连OOP之间，有些设计模式就不是互通的，当然这些都是题外话了。<br />最后总结一下自己学习设计模式的阶段过程：<br /><span style="color: #3366ff">GOF---> Java与模式 ---> 面向对象设计的基本原则 ---> 用原则自行分析既有设计模式 ---> 忘掉设计模式！ ---> 开始动手干！</span><br />最后带！号的阶段还没有开始处于&ldquo;意淫&rdquo;阶段，不过当当&ldquo;自淫者&rdquo;也不妨，别怕失败，工资是靠失败积累起来地！
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/168069#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 05 Mar 2008 10:26:22 +0800</pubDate>
        <link>http://Pipboy.group.javaeye.com/group/blog/168069</link>
        <guid>http://Pipboy.group.javaeye.com/group/blog/168069</guid>
      </item>
      <item>
        <title>四色原型（二）</title>
        <author>xufei0110</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://xufei0110.javaeye.com">xufei0110</a>&nbsp;
          链接：<a href="http://Pipboy.group.javaeye.com/group/blog/136719" style="color:red;">http://Pipboy.group.javaeye.com/group/blog/136719</a>&nbsp;
          发表时间: 2007年10月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          上回我们谈论了四色原型的基本定义，四色原型好像是这样一个场景抽象：某人参与某活动对某事情操作，基本上我们人类的所有活动都可以用这段抽象来表达，这说明四色原型帮助我们更快地分析分辨事物。
<p>　　下面我们以Java Modeling in Color with UML书中案例详细说明一下四色图深入意义，如下图：</p>
<p><img src="http://www.jdon.com/mda/images/foursample.jpg" height="444" alt="四色图" width="488" /></p>
<p>　　我们按照某人对某东西做某事的思路来理解上图，不同的是，上图中研究的不是某人(party)如何，而是研究Thing，如图中绿色类图中&lt;
<thing></thing>
&gt;的标识。这样，这张图表达的是某个东西在一个活动或流程中发生的一些行为。</p>
<p>　　蓝色的description种类原型负责寻找这类东西中一个实例（图中findAvailable方法）并计算可用实例的数量，这两种功能都需要和左边绿色party对象交互。绿色的thing是判断自己是否可用（图中isAvailable方法），如果可以就返回一个优化的值；如果不是，向蓝色的种类原型要求返回一个缺省值；黄色角色是判断这个东西是否适合它的角色，这几种方式都是和粉红的moment-intervals发生交互的。粉红的moment-intervals原型可以创建这样一个东西实例（图中makeMomentInterval方法，支持业务过程来创建）；增加细节（图中addDetail方法）或组成部分；并且计算总和(calcTotal)；它也接受外界消息查询当前活动是否完成或者取消了（图中Complete和Cancel方法）等等。</p>
<p><strong>用途之一：有助于正确的域建模</strong></p>
<p>　　当我们接到一个软件项目时，首先是了解业务需求，这个过程是一个交互逐步深入的过程，了解业务需求有多种方式，如国外普遍推崇的Use Case，画出用例图和客户反复确认；或者在中国，由于客户层次限制，我们可能使用界面驱动方式，美工制作员首先制作出界面流程，供客户直观确认，反正方式多种多样，这不在本文讨论范围之内。</p>
<p>　　本文关心的是，当你采集到正确的业务需求后，你是使用什么方式把它传导到软件系统中，或者说：如何保证软件系统解决的正是你的业务需求？如何保证这两者之间对接完全正确，因为对接传导不正确导致软件系统失败的案例太多了，最后表现为软件人员和客户互相推委，损失的是双方时间和精力，这是谁也不想看到的，可是难道没有可依赖的科学方法吗？</p>
<p>　　这正是域建模所要解决的，每个业务需求总是有一定的解决问题，一个业务需求不可能解决世界上所有问题，所以业务需求提出的是一定范围内的问题，是一种域问题，而随之解决方案软件系统也是一种域解决方案，所以，在这个域中正确将业务需求传导到软件系统很正确，这就取决于我们的域建模。<br />
<br />
　　谈到域建模，有人会问：在域建模概念出现之前，我们也做软件系统，那时是用什么分析方法？很显然，我们是使用数据库建模（使用powerDesign这样传统工具），依靠分析人员对这个行业过去的经验和走过的路，设计出数据表结构，然后交给程序员写SQL等数据CRUD增删改查方法，这是一种完全依赖数据库的分析设计方法，笔者已经在&ldquo;<a href="http://www.jdon.com/artichect/dbover.htm" target="_blank">数据库时代终结</a>&rdquo;一文中指出过，这种方式已经过时，数据库建模不能完全反应系统的全部特性和需求，使用同样一套数据库，完全由两套优差不同的设计方案和代码，从JiveJdon3.0和JiveJdon2.5两个版本完全可以明白： <a href="http://cosoft.org.cn/project/showfiles.php?group_id=5298">http://cosoft.org.cn/project/showfiles.php?group_id=5298</a>，这两个版本都是使用同一个数据库结构，但是却是完全截然不同的设计和代码，软件的维护型和可扩展性就完全不同。<br />
<br />
　　数据库驱动分析不仅带来业务需求和软件系统对接不正确，导致软件系统失败，而且，这种分析方法过于依赖系统分析人员的经验背景，导致系统分析员都是业务人员，而非专门的建模专家，不懂设计的业务人员还是无法做到软件系统和业务需求的正确对接，还是范域范围不对的老问题。</p>
<p>　　还有一种观点认为，域建模不过就是使用UML画出类图，他以前设计过这个领域的数据表，换成类图就可以了，类图和数据库建模图似乎表面一样，好像都是静态关系表达，其实不然，类图其实是动态的，是一种隐形动态，使用四色图表达的类图则是一种包含顺序图的完全动态图，可以说类图是立体多维的，而数据库模型图则是完全静态的。 </p>
<p>　　那么当我们进行系统分析设计时，如果有一个类，到底应该给它标记什么颜色呢？也就是说将其归类为哪个原型呢？通过这种归类上颜色可以确证我们这个类提取的是否正确？或者可以说，我们可以按照四色原型从业务需求中提取抽象类，从而画出类图。我们可以按照下面考虑顺序：</p>
<p>　　第一：它是不是依赖时间上瞬间或一段短时间存在的，是不是业务需求需要跟踪记录的对象？如果是，它就是momentinterval原型（简称MI）。</p>
<p>　　第二：然后，它是不是角色呢？如果是，就属于黄色Role原型。</p>
<p>　　第三：然后，它是不是属于一种目录式的种类性质对象，或者代表一组呢可以反复使用的概念，如果是，它就是蓝色description原型。</p>
<p>　　第四：最后，它是某人或组织？或者是某个地方或者某个东西？那它就是绿色的party, place, or thing （简称PPT）。 </p>
<p>　　可以将一个复杂的系统划分成一块一块，从而有助于设计实现，当我们一个系统有好几百个类图时，如果不采取四色原型进行归类，那么无疑很混乱，甚至类图提取不正确，概念重复，甚至只有在系统代码实现时才会发现如此严重问题，这对于分析设计来说无疑时重大打击。</p>
<p><strong>Domain-Neutral Component(DNC)</strong></p>
<p>　　一个业务系统是由多个四色图反复拼装而成，我们称为这种现象是<strong>Domain-Neutral Component</strong>模式，如下图（图片来自<a href="http://www.step-10.com/objectmodeling/TheDomainNeutralComponent.html" target="_blank">Step10</a>）所示：<a href="http://www.jdon.com/mda/images/dnc.png" target="_blank"><img src="http://www.jdon.com/mda/images/dnc.png" border="0" height="500" alt="Domain-Neutral Component" width="580" /></a></p>
<p>　　这样，我们可以将一个复杂可能是成千上万个类的类图划分成一个个小碎块，达到清晰分类的目的。你可以使用这种基于语义的类图模板进行任何系统的域建模，DNC最好的优点是异常的简单好用，你不必将你的模型Model填入DNC，而是DNC指导帮助更加完整地建模。</p>
<p>　　很多人认为类图是静态的；而顺序图是动态的，其实类图是隐形的动态；而顺序图只是显式的动态，顺序图是将动态执行过程完全表现出来，而我们从类图上好像看不到这点，其实你可以在四色类图中发现更多顺序图的影子，四色图中几乎无需另外使用顺序图来补充表达，而整个DNC内部的所有交互都是这样的，这无疑是令人激动的，也就是说，使用包含四色图的DNC已经可以完全表达一个系统了。</p>
<p>　　我们先看看类图中是如何虚拟表达业务三维系统中的联合association：</p>
<p align="center"><img src="http://www.jdon.com/mda/images/classsample.jpg" height="172" alt="类图" width="237" /></p>
<p align="left">　　如图中上半部分，左边和右边两个类的关系association是用0..*表达，这说明是一个一对多关系，实际意思是图中下半部分，一个左边对应右边多个，所以，我们要从图中表达看到更加深远的意思，上半部分比下半部分表示更加节省空间，也只是空间上简化。</p>
<p align="left">　　那么，如果左边的对象向右边的对象发送消息，形成交互动作了，是不是一定要使用方法method和顺序图来表示，为什么我们不能象上面空间简化一样进行动态简化，如下图：</p>
<p align="center"><img src="http://www.jdon.com/mda/images/classsample2.jpg" height="104" alt="顺序图" width="226" /></p>
<p align="left">&nbsp;</p>
<p>　　我们可以在类图中表达顺序交互动作，这就是DNC作出的一个贡献。所以从一张DNC图的关系中，我们可以清楚的表达前后发生的循序调用。比如上面DNC图中一旦一个PartyRole访问Momentinterval，将首先访问PriorMI，还有MomentintervalDetails（当然，该图中没有列出方法，所以具体确切走向无法得知）。</p>
<p><strong>十二种复合组件(Compound Components)</strong></p>
<p>　　这12种复合组件是所有企业业务系统的抽象，说白一点，所有企业系统业务需求分析到最后，基本上都可以用这12种复合组件代表，换句话说：搞懂这12个组件模型，你就基本能迅速分析弄懂几乎的企业系统，从而进行快速的设计编码，这12种组件可以说是业务需求的复用，从而能使我们站在前人的基础上更快更准进入企业软件系统的分析和设计开发。</p>
<p>　　这12种复合组件是：</p>
　　 　　
<table border="0">
    <tbody>
        <tr>
            <td>Make a Buy<br />
            Sell<br />
            Relate<br />
            Coordinate and Support<br />
            MaterialResourceMgmt<br />
            ProductSaleMgmt<br />
            HumanResourceMgmt<br />
            ProjectActivityMgmt<br />
            FaclilityMgmt<br />
            CashSakeMgmt<br />
            RelationshipMgmt<br />
            AccountingMgmt<br />
            ManufacturingMgmt<br />
            CustomerAccountMgmt<br />
            DocumentMgmt<br />
            InventoryMgmt </td>
        </tr>
    </tbody>
</table>
<p>　　需要详细了解这些原型组件可参考Java Modeling in Color with UML一书。<br />
</p>
<p><strong>Jdon框架应用</strong></p>
<p>　　Jdon Framework作为一个新兴的开源框架，可能有很多人对其是否能够承受复杂应用表示怀疑，其实这些我们都是可以从四色图理论上进行论坛证。</p>
<p align="center">　　以Jdon框架应用JiveJdon3.0为例，该系统使用Jdon框架其实已经完成了四色图需求，如下图<img src="http://www.jdon.com/mda/images/four.jpg" height="176" alt="四色图" width="350" /></p>
<p align="left">　　这已经说明使用Jdon框架可以完成一个四色图需求实现，而根据DNC理论，复杂的系统基本是由多个四色图重复组成，因此，我们完全可以反复使用Jdon框架，通过完成一个个四色图这样的基本单元，从而以组件拼装方式完成一个较为复杂的应用系统。</p>
<p align="left">　　四色图和DNC理论实际上是我们面对大型纷繁复杂需求时的一个定心丸，同时也是检验一些新兴理论开放框架的一个基础平台。从此我们可以轻松地使用四色图分解出项目需求，从而确保项目系统实现完全符合原始需求，跨越项目需求和项目实现不对接这个鸿沟，也许以后我们不再会发生下面的情况：当我们辛辛苦苦用最新绚丽的技术完成软件系统后，兴致勃勃介绍给用户时，用户却说：这不是我想要的东西。</p>
          <br/>
          <span style="color:red;">
            <a href="http://Pipboy.group.javaeye.com/group/blog/136719#comments" style="color:red;">本文