Java.use(better);

前の記事次の記事
Java.use(better);


Episode#05

Map の効能 -- 配列と別れる50の方法


《関連記事》

《目的》

OOP の障害となる「配列」の隘路を確認した後で、Map を利用して問題解決を図るとともに、配列の「添字式」を抽象化して「ポリモフィズム」を促進する術を紹介します。

《動機》

Java は、純粋な OOP を目指すのではなく、SP との中庸を選択しました。そのため「配列」が混在すると、すべてを OOP の枠組みで統一的に扱うのが困難です。複雑なデータ構造を配列で実現するのは面倒なだけでなく、コードが複雑で見通しも悪くなるので、避けたいものです。たとえば、連想配列は、写像(キーと値の組)を扱うのに便利です。それを容易にする Map が、クラスライブラリーとして、言語仕様の一部として提供されると、ソフトウエア開発の能率が上がります。

添字式を抽象化すると、異なる種類のオブジェクトに有効な「ポリモフィズム」を実現できます。すると、要求仕様の変更にも柔軟に対処できるので、ソフトウエア開発の能率が上がります。

■ 配列の隘路

ソースコードに含まれる英文字(アルファベット)の度数分布表(ヒストグラム)を作成する事例で話を進めます。

組み込みのデータ構造の中から、この問題解決に必要なのは、任意の要素を管理できる「配列」です。そこでは、固定された境界条件を満たすときだけ、特定のデータにアクセスできるという流れに沿って、アルゴリズムが確定します。

実行すると、次の結果が得られ、

src/Source.java
@: 623
A: 54
B: 5
C: 37
D: 16
E: 103
   ...
X: 4
Y: 7
Z: 0
[1425]

度数が最も多い英文字は 'E' だと分ります。実行したコードの断片に着目します。

    for (String line: new Source(pathname))
      for (String token: new ExTokenizer(line))
        histo.addAll(token);
    System.out.println(pathname);
    System.out.println(histo);

ExTokenizer は、Episode#01 で紹介しました。ソースコードの各行 line からトークン token を取り出すときに、拡張 for 文が使えるので、コードが簡潔で見通しも良くなります。

これは、次のように実現します。

class Histogram1 ...
  protected final char lowerLimit = '@';
  protected final char upperLimit = 'Z';
  private int[] values = new int[size];

  void add(char c) {
    int index = c - lowerLimit;
    if (c <= lowerLimit || upperLimit < c) {
      index = 0;
    }
    values[index] += 1;
  }

'A' から 'Z' までの文字を、配列の先頭からのオフセット値 index に換えて、配列の添字に指定します。たとえば、文字 'C' のオフセット値は 'C'-'@' になるので、その度数を values[3] に集計します。それ以外の文字なら、その度数を配列の先頭 values[0] に集計します。

配列を扱うときに問題となるのは、添字の範囲を超えないような配慮が必要になることです。たとえば、if に続く条件式などが、その典型です。そのため、コードが複雑で見通しも悪くなるだけでなく、バグの温床になりがちです。

 ↑ TOP

》作業中です《

update*13/01/23 3:44:13

♪ 三が一(みつがいち)



出典 ☞ http://shimayu.co.jp/modules/myalbum/photo.php?lid=84