データ管理へ戻る | サンプル集目次へ戻る

実行結果
Categoryサンプルソース
ファイルから読み込んだデータを、カテゴリーごとに分類。画面表示とデータ管理の分離は、プログラム設計の基本です。
Category.java
ComicChar.java
DataManager.java
/**
 * 愛のJava256本ノック for Java 5.0
 * Javaサンプルソース ver0.2C "Category"
 * Category.java 「Setを使ったカテゴリー分類」
 *
 * 2005/09/23 制作:安永ノリカズ
 *
 * 【コンパイル&実行方法】
 *     >javac *.java
 *     >java Category
 * 【キーワード】
 *     クラス設計(class design), Model(処理), View(表示)
 * 【試してみよう】
 *     CSVにデータを追加し、カテゴリーが増えるのを確認する。
 *     編集した内容をCSVに書き出す「保存」機能をつける。
 *     
 */
import java.awt.BorderLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.String;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextArea;

public class Category extends JFrame implements ActionListener {
    JComboBox I00;
    JTextArea I01;
    DataManager I02;
    
    public Category() {
        I02 = new DataManager();
        // カテゴリーのリストを取得して、コンボボックスを作成
        I00 = new JComboBox(I02.M00());
        I01 = new JTextArea();
        add(I00, BorderLayout.NORTH);
        add(I01, BorderLayout.CENTER);
        
        I00.addActionListener(this);
    }
    
    public void actionPerformed(ActionEvent A00) {
        String L00 = (String)I00.getSelectedItem();
        // 選択されたカテゴリーに含まれるデータを検索
        List<ComicChar> L01 = I02.M01(L00);

        I01.setText("");
        
        for (ComicChar L02 : L01) {
            I01.append(L02.I01 + "\n");
        }
    }

    public static void main(String[] A00) {
        Toolkit.getDefaultToolkit().setDynamicLayout(true);

        Category L00 = new Category();
        L00.setTitle("カテゴリーごとに分類");
        L00.setDefaultCloseOperation(EXIT_ON_CLOSE);
        L00.setSize(320, 240);
        L00.setVisible(true);
    }
}

/* ■ クラスの外でちょっと一言 ■
CSVファイルからデータを読み込み、カテゴリーごとに分類して表示するプログ
ラムです。まずはプログラムを動かし、付属のCSVファイルの中身と見比べてく
ださい。

このサンプルは、Category、DataManager、ComicCharの3つのクラスで構成され
ており、それぞれで役割を分担しています。Categoryクラスは、GUIやイベント
処理などを担当。ComicCharは1件のデータを表すクラスで、そのComicCharのリ
ストをDataManagerクラスが管理する構造になってます。

クラス設計において、「画面表示」と「データ管理」を分けるのは基本中の基
本。クラス分けに悩む場合は、まずここを取っ掛かりにすればいいかと思いま
す。
 */
↑ 先頭へ戻る
/**
 * 愛のJava256本ノック for Java 5.0
 * Javaサンプルソース ver0.2C "Category"
 * ComicChar.java 「Setを使ったカテゴリー分類」
 *
 * 2005/09/23 制作:安永ノリカズ
 *
 * 【コンパイル&実行方法】
 *     >javac *.java
 *     >java Category
 * 【キーワード】
 *     コンストラクタ(constructor)
 * 【試してみよう】
 *     Category.javaを参照。
 */
import java.lang.String;

public class ComicChar {
    String I00;    // カテゴリー名
    String I01;    // キャラクター名

    public ComicChar(String A00, String A01) {
        this.I00 = A00;
        this.I01 = A01;
    }
}

/* ■ クラスの外でちょっと一言 ■
これは、単純にデータを管理するクラスです。comic_char.csvの形式が、
  [カテゴリー名],[キャラクター名]
のようになってますので、それぞれのデータを格納するフィールドを用意してい
ます。CSVファイルの行数分、このクラスのインスタンスが生成されますので、
CSVファイルの中身を確認しておいてください。

それにしても『北斗の拳』は熱いぜ! 熱くて死ぬぜ!
 */
↑ 先頭へ戻る
/**
 * 愛のJava256本ノック for Java 5.0
 * Javaサンプルソース ver0.2C "Category"
 * DataManager.java 「Setを使ったカテゴリー分類」
 *
 * 2005/09/23 制作:安永ノリカズ
 *
 * 【コンパイル&実行方法】
 *     >javac *.java
 *     >java Category
 * 【キーワード】
 *     ジェネリックス(generics), 拡張forループ, Set(集合), List(リスト), 
 *     equalsによる文字列の比較
 *     
 * 【試してみよう】
 *     Category.javaを参照。
 */
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.String;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class DataManager {
    static final String C00 = "comic_char.csv";
    List<ComicChar> I00 = new ArrayList<ComicChar>();

    public DataManager() {
        // CSVファイルからデータを読み込んでリストに追加
        try {
            BufferedReader L00 = new BufferedReader(new FileReader(C00));
            String L01;
            while( (L01 = L00.readLine()) != null ) {
                String[] L02 = L01.split(",");
                I00.add(new ComicChar(L02[0], L02[1]));
            }
            L00.close();
        } catch(FileNotFoundException L03) {
            System.out.println(C00 + "が見つかりませでした。");
        } catch(IOException L04) {
            System.out.println(C00 + "を読み込めませんでした。");
        }
    }
    
    // カテゴリーの配列を返す
    public String[] M00() {
        Set<String> L00 = new LinkedHashSet<String>();
        
        for (ComicChar L01 : I00) {
            L00.add(L01.I00);
        }

        return L00.toArray(new String[0]);
    }

    // カテゴリーを指定して検索
    public List<ComicChar> M01(String A00) {
        List<ComicChar> L00 = new ArrayList<ComicChar>();

        for (ComicChar L01 : I00) {
            if (L01.I00.equals(A00)) {
                L00.add(L01);
            }
        }

        return L00;
    }
}

/* ■ クラスの外でちょっと一言 ■
データの管理を担当するこのクラスには3つの機能が備わってます。

まずは、コンストラクタで外部ファイルからデータを読み込む機能。読み込まれ
たデータは1件ごとインスタンス化されて、Listに追加されます。以降、この
Listから、随時必要なデータを取り出すことになります。コンストラクタなん
で、ファイルの読み込みは最初の1回だけですね。

次は、カテゴリーを集計する機能。読み込んだListから、カテゴリーを取り出し
てますが、ポイントは、重複を省く必要があるということ。そこでコレクション
フレームワークのSetの登場です。Setは、数学でいうところの「集合」で、重複
要素を持たないという性質があります。こういう集計にはぴったりですね。

Setから配列への変換にtoArrayメソッドを使ってますが、その引数にString[0]
と、長さ0の配列を渡してます。このメソッドは、「配列のサイズが十分でない
場合は、同じ実行時の型で新しい配列が格納用として割り当てられる」そうなの
で、配列の長さは0でOK。大事なのは配列の型だけです。

最後に、指定されたカテゴリーのデータだけを取り出す機能。元のListから該当
するデータを選んで、別のListに追加しています。「毎回新しいListを生成し
て、メモリは大丈夫か?」という気がしますが、Listにはインスタンスの参照が
入るだけなので、それほど資源は消費しません。

ジェネリックスのおかげで面倒な型変換がなく、拡張forループですっきりと全
要素の走査ができてます。このへんは、J2SE 5.0さまさまですね。
 */
↑ 先頭へ戻る

安永ノリカズのゲーム制作&Javaサンプル集 / Java初心者用サンプル集『愛のJava256本ノック』