竹形誠司 ブログ
Java+MySQL+Tomcat    »トピック一覧
掲示板へのスパムが多いため、「ご質問」のコーナーはユーザー登録制とさせていただきました。お手数ですが、上の「新規ユーザーの登録」メニューより登録をお願いします。
帳票Web
アプリケーション

受注開発始めました
詳しくは こちら
竹形 誠司 著/ラトルズ刊
JSP帳票アプリケーション実践開発入門
JSP帳票アプリケーション
実践開発入門

JSP業務アプリケーション短期開発入門
JSP業務アプリケーション
短期開発入門

Java+MySQL+Tomcatで始めるWebアプリケーション構築入門
Java+MySQL+Tomcatで始めるWebアプリケーション構築入門

Java+MySQL+Tomcatで作る掲示板とブログ
Java+MySQL+Tomcatで作る
掲示板とブログ
ツリー構造の表示方法
by 竹形 誠司[takegata]
掲示板などのコメントをツリー形式で表示する方法についてのメモ。

各レコードがidを持ち、子供は親のidをparentIdとして持っているものとします。たとえば、こんな感じのPersonクラスを想定します。
class Person{
    //フィールド
    int _id;
    int _parentId;
    String _name;

    //コンストラクタ
    Person(int id,int parentId,String name){
        _id=id;
        _parentId=parentId;
        _name = name;
    }
}
Personクラスのコンストラクタでは、最初の引数がid、2番目の引数がparentId、3番目の引数が名前です。親を持たない場合はparentIdに0をセットします。ArrayListを用意して、次のような感じのデータを入れ、最後にgetChildrenを呼びます。
public class DispTree{
    static ArrayList<Person> alPerson = new ArrayList<Person>();
    public static void main(String[] args){
        alPerson.add(new Person(1,0,"ナミヘイ"));
        alPerson.add(new Person(2,1,"サザエ"));
        alPerson.add(new Person(3,1,"カツオ"));
        alPerson.add(new Person(4,1,"ワカメ"));
        alPerson.add(new Person(5,2,"タラ"));
        alPerson.add(new Person(6,4,"ヒラメ"));
        alPerson.add(new Person(7,5,"タラコ"));
        alPerson.add(new Person(8,2,"ブリ"));
        alPerson.add(new Person(9,8,"ハマチ"));
        alPerson.add(new Person(10,9,"イナダ"));
        alPerson.add(new Person(11,8,"カンパチ"));
        getChildren("",0);
    }
上の例では、ナミヘイに親はなく、サザエ、カツオ、ワカメの親がナミヘイでタラ、ブリの親がサザエで、タラコの親がタラで、ハマチ、カンパチの親がブリで、イナダの親がハマチで、ヒラメの親がワカメです。

getChildrenは、「子のリストを作るメソッド」です。この中でそれぞれの子について、「子のリストを作るメソッド」を呼び出します。つまり、自分で自分を呼び出すわけです。このような呼び出し方を「再帰呼び出し」といいます。無限ループになりそうでちょっと恐いですね。コードはこんな感じです。
    static void getChildren(String leader,int parentId){
        ArrayList<Person> alChildren = new ArrayList<Person>();
        for(Person person:alPerson){
            if(person._parentId==parentId){
                alChildren.add(person);
            }
        }
        int intCount=0;
        for(Person person:alChildren){
            intCount++;
            System.out.print(leader);
            if(intCount<alChildren.size()){
                System.out.print("┣");
                System.out.println(person._name);
                getChildren(leader+"┃",person._id);
            }else{
                System.out.print("┗");
                System.out.println(person._name);
                getChildren(leader+" ",person._id);
            }
        }
    }
getChildrenメソッドには、for文が2つあります。最初のfor文では、指定されたparentIdを持つレコード(兄弟)のリストを作っています。次のfor文で兄弟の一人一人について処理を行います。

2つ目のfor文では、ツリー構造を分かりやすく示すために罫線を使っています。
まず、leaderを表示します(最初の階層では何も表示しません)。

自分の下にも兄弟がいれば名前の前に「┣」を表示し、自分の名前を表示してからleaderに「┃」を追加し、getChildrenを呼び出します。

自分の下に兄弟がいなければ「┗」を表示し、自分の名前を表示してからleaderに全角スペースを追加してgetChildrenを呼び出します。

上のコードを実行すると、表示は次のようになります。
┗ナミヘイ
 ┣サザエ
 ┃┣タラ
 ┃┃┗タラコ
 ┃┗ブリ
 ┃ ┣ハマチ
 ┃ ┃┗イナダ
 ┃ ┗カンパチ
 ┣カツオ
 ┗ワカメ
  ┗ヒラメ
ソースソース
disptree.java

投稿:竹形 誠司[takegata]/2008年 06月 05日 05時 38分 /更新:2008年 06月 05日 05時 54分
ツリー構造の表示方法(JSPの場合)
by 竹形 誠司[takegata]
JSPの場合は、<%! と %>を使って内部クラスやフィールド、メソッドを記述します。こんな感じです。
<%@ page contentType="text/html; charset=utf-8"%>
<%@ page import = "java.util.ArrayList"%>
<HTML>
<HEAD><TITLE>tree</TITLE></HEAD>
<BODY>
<%!
class Person{
    int _id;
    int _parentId;
    String _name;
    Person(int id,int parentId,String name){
        _id=id;
        _parentId=parentId;
        _name = name;
    }
}
ArrayList<Person> alPerson = new ArrayList<Person>();
StringBuffer sb = new StringBuffer();
void getChildren(String leader,int parentId){
    ArrayList<Person> alChildren = new ArrayList<Person>();
    for(Person person:alPerson){
        if(person._parentId==parentId){
            alChildren.add(person);
        }
    }
    int intCount=0;
    for(Person person:alChildren){
        intCount++;
        sb.append(leader);
        if(intCount<alChildren.size()){
            sb.append("┣");
        }else{
            sb.append("┗");
        }
        sb.append(person._name);
        sb.append("<BR>");
        if(intCount<alChildren.size()){
            getChildren(leader+"┃",person._id);
        }else{
            getChildren(leader+" ",person._id);
        }
    }
}
%>
<%
alPerson.add(new Person(1,0,"ナミヘイ"));
alPerson.add(new Person(2,1,"サザエ"));
alPerson.add(new Person(3,1,"カツオ"));
alPerson.add(new Person(4,1,"ワカメ"));
alPerson.add(new Person(5,2,"タラ"));
alPerson.add(new Person(6,4,"ヒラメ"));
alPerson.add(new Person(7,5,"タラコ"));
alPerson.add(new Person(8,2,"ブリ"));
alPerson.add(new Person(9,8,"ハマチ"));
alPerson.add(new Person(10,9,"イナダ"));
alPerson.add(new Person(11,8,"カンパチ"));
getChildren("",0);
%>
<DIV STYLE="line-height:16px;">
<%=sb.toString()%>
</DIV>
</BODY>
</HTML>
投稿:竹形 誠司[takegata]/2008年 06月 05日 06時 03分 /更新:2008年 06月 05日 06時 03分