Java 一覧

CloneableとCloseable

Javaの1.5 ( 5.0 ) にはCloseableというインターフェースが導入されています。このインターフェース自体は、閉じることができるソースに対して実装されています。宣言されているメソッドは、close()です。Reader や Writer の内部では、リソースへアクセスできる変数に null を代入することによって切り離している場合が多いです。

それに対して、1.0から存在している Cloneable は、インスタンスのコピーを生成できるクラスが実装しています。このインターフェース自体はメソッドは定義していませんが、Objectクラスのclone()をオーバーライドすることによってcloneメソッドが使用できるようになります。Cloneableインターフェースを実装していない場合はcloneメソッドを呼び出しても、例外(CloneNotSupportedException)がスローされます。

さて、見た目はよく似ていますが、使い方はかなり違います。基本的に、よく知られているクラスの中ではCloneableは実装されていない場合が多いので、一度確認してみると良いかと思います。

JavaのMapを使用するときの注意

  • 更新日:
  • Java
  • API

これはAPI上でも書かれていることですが、敢えてメモしておきます。

Mapで使用するキーは、hashCode()とequals(Object)を使用して同一かどうかを判定します。なので、equals(Object)でtrueを返すオブジェクトは、hashCode()も同一である必要があります。ただし、逆はそうでなくてもよくて、hashCode()が同一でも、equals(Object)がtrueを返さなければならないわけではありません。

もし、この規約が守られない場合は、キーとして使用するのは不適格です。なぜなら、Map中のエントリーと比較するときは、hashCode()が同一であるかどうかを調べてから、equals(Object)で調べるからです。hashCode()がオーバーライドされない場合、equals(Object)がtrueであっても、異なるオブジェクトとして認識されてしまい、Mapとしての機能を果たしません。

Math#pow(double,double)

  • 更新日:
  • Java

Mathクラスでは、ネイティブで速く動作する機構がある場合は優先的に使用するという仕様なんですが、では単純な計算の場合はどうなのかを比較してみました。

たとえば、2乗を計算する場合。長大な配列を用意して、全ての要素の演算を処理し終えるのにどのくらい時間がかかるかを比較しました。10000個では差が出なかったので、5,000,000個(5百万個)の要素を持つ配列で試しました。結果は・・・。
配列版 : 78ms
Math版 : 437ms

けっこう大きな差が出ました。では、3乗では・・・?
配列版 : 79ms
Math版 : 2765ms

これは大きいですね。 C言語のライブラリでもそんな感じですが、指数が整数で既知の場合は、直接掛け算した方が速そうです。ちなみに実行環境は、WindowsXPPro、1.86GHz/767MB、J2SE DK5.0Update5でコンパイル。オプションは、JVMのヒープ領域を100MBに指定した以外はデフォルト。

キーを2つ持つマップの作成

  • 更新日:
  • Java

マップと言うと、地図を思い浮かべる方が多いと思いますが、プログラミングでは「あるオブジェクトに対応づけられているオブジェクトの集合」ってことになります。鍵の束と、金庫がたくさんあるような状態って言えばいいんでしょうか。

Javaでデフォルトで提供されているMapは、キーが1つに対して値が1つなんですが、これだとやや不便な場合があります。たとえば、学校のクラスの生徒数を調べたい場合に、学年とクラス番号をキーとして扱えればいいなぁというような状態。ま、単純に学年とクラス番号を1つのオブジェクトとして扱って、1つのキーとするのが一番手っ取り早いんですが、そのために毎回オブジェクトを作成するのもなんかもったいない気がする、てことで2つキーを持つマップを作ってみました。

初めはかなり思いつきで、HashMapの模倣版を作成。適当に作ったわりには簡単にできた感触。そのあとは、JavaAPIを見習って、その上位のAbstractクラスを作ってみました。AbstractMapを参考にしたんですが、かなりよくできてます。パフォーマンスはおいといて、端的に実現するにはあんな方法があるんですね。entrySetを実装するだけで、ほとんどのメソッドが使用できるなんてかなりありがたい話です。

JavaのAPI(Integer編)

  • 更新日:
  • Java

Javaのバージョンも5.0になって久しいですが、たまたまAPIのIntegerのページを見ていたらいろんなメソッドが追加されてました。使い方もよく分からないものがあるんですが^^;

5.0で追加されたものをざっと見てみると、intをビットで表現して、その補数を取ったり回転させたりする動作が追加された模様。フィールドもビットで表現したときの長さを示す「#SIZE」っていうのが増えてました。でも、今のところ僕の研究などでは使う気配はなさそう。

プリミティブ型での0除算

  • 更新日:
  • Java

Javaでかなり使用頻度の高いプリミティブ型。でも、このプリミティブ型の中で0除算を行ったときの挙動はそれぞれ違います。

プリミティブ型と言っても基本はラッパークラスなわけなんで、そのクラスの詳細を知ることでどのようになるかが予測できます。Double型とFloat型はスタティックフィールドとして「NaN」を持っているので、double、もしくはfloatで0除算を行うとNaNが返ってきます。しかし、NaNを持たないByteやInteger、Short、LongなどではArithmeticException(Runtime Exception)がスローされます。

String#split(String)の実験

  • 更新日:
  • Java

ふとした好奇心で、String#split("")を実行するとどうなるだろうと思って試してみました。

たとえば、"abcde".split("")とした場合。結果は、
String[0] = ""
String[1] = "a"
String[2] = "b"
String[3] = "c"
String[4] = "d"
String[5] = "e"
でした。なぜか一番初めに空文字が入ります。

Javaでメモリリーク

  • 更新日:
  • Java

大学の研究の関係で、いろいろなことを順番に処理させたいってことがあります。そんなときに、こんなコードを書くとえらい目に遭います。

public static void main(String[] args){
    List<Executable> list = getTasks();
    for(Executable e:list){
        e.execute();
    }
}

これは、ただ単にリストの中身を実行してるだけなんですが、もしこのExecutableクラス中で大きなデータを保持したまま終了するようなソースを書いていた場合、いくらメモリがあっても足りません。そんなわけで、実行したあとのいらないインスタンスはさっさと切り離した方がベターです。

public static void main(String[] args){
    List<Executable> list = getTasks();
    for(Iterator<Executable> it = list.iterator();it.hasNext();){
        e.execute();
        it.remove();
    }
}

Enumerationインターフェースが推奨されない理由はここにあるのかもしれませんね。Collectionインターフェースを実装してるクラスでは、iteration中の要素の削除は例外のもとだし。

JVMのオプション

  • 更新日:
  • Java

javaのプログラムではVMがヒープ(メモリ)のサイズを決定します。しかし、大きなデータを扱う場合や、より高速に動かしたい場合はこのデフォルトのサイズでは小さい場合があります。

このようなときに、プログラムの実行時にオプションとして値を渡してやることで、ヒープの割当量を変更することができます。たとえば、初期ヒープサイズを変更する場合は「-Xms」、最大サイズを変更する場合は「-Xmx」です。

仮に60MBのヒープ領域を割り当てたいとすると、「java -Xms60M -Xmx60M mainClass」とすることで実現することができます。

StringBuilder

  • 更新日:
  • Java

StringBuilderは、文字列を連結したり、ある場所に挿入したりできるクラスです。Stringクラスが不変なのに対して、こちらは可変クラスです。

同様の可変クラスとして、StringBufferがあります。こちらは同期が取れるクラスなので、複数のスレッドにまたがって処理される場合は有効です。ただし、単一スレッドの場合はStringBuilderの方が高速です。

このコンストラクタは4種類あります。引数なし、CharSequence、int、Stringをそれぞれ引数に持ちます。これらのうち、CharSequence、Stringはインスタンスの持つ文字列を決定するためにあるのに対して、int型は初期容量を決定するためにあるので注意が必要です。

このページの上部へ

About

tetsuの日記・雑記です。
日々経験したことを記録していきます。

広告

サイト内検索

最近のピクチャ

  • リアディレーラ

月別アーカイブ

最近のコメント