意外と使われていないけど便利なCommons

Javaを仕事で書いている人なら、大半の人が知っていると思うApache Commonsですが、折角プロジェクトでCommonsが使えるのにメソッドを使わないという事例をよく見るので、少し便利な物を書き連ねてみようかと思います。

あ、主旨は何が何でもCommons使えー、というわけではなく、折角Commons入ってるプロジェクトって多いんだから、その中身のUtilメソッドを使った方が苦労が少ないよーということです。
他のライブラリ(Guavaとか独自のとか)で同じ処理があるなら、そっちを使ってもよいと思いますが、べた書きするぐらいならこっちを使いましょうってことで。

StringUtils#isEmpty

API - StringUtils#isEmpty

コレ使いたいためだけにStringUtils使ってないか疑惑があるぐらいには一番よくつかわれている。
文字列が null or "" ならtrueを返します。
あと、この逆のisNotEmptyというメソッドも準備されている。

StringUtils#equals

API - StringUtils#equals

Javaでは文字列クラスにequalsの実装があるという残念な仕様のせいで、同値関係を表現できないという問題がある。
具体的には、null.equals("") と "".equals(null)で挙動が異なる*1
この理由により、要素がnullではない方を左辺にもってくるのがJavaのイディオムだが、両方ともnullの可能性がある場合はStringUtils#equalsを利用すると楽。

ただし、StringUtils.equals(null, null)はtrueを返すので、この処理がまずい場合のみ何らかの対応が必要。

StringUtils#join

API - StringUtils#join

こんなメソッドが転がっているのをよく見る。それも、1か所ならともかく複数に。
メソッドにまとめられていたら良い方で、書きなぐられている場合も多々(--;

private String myjoin(List<String> xs, String separator) {
  String[] array = xs.toArray(new String[0]);
  StringBuilder buf = new StringBuilder();
  for(int i = 0; i < array.length; i++) {
    buf.append(array[i]);
    if (i != array.length-1) {
      buf.append(separator);
    }
  }
  return buf.toString();
}

これだけでも、xsの要素数が0の場合、1の場合にそれぞれどうする、とか、意外にも複雑だったりする。
人によって実装が微妙に変わるので、その結果バグを踏んでしまったりする。

そんな時には、joinというメソッドがあるのでこれを利用してしまおう。

    StringUtils.join(xs, "");  // 単に結合
    StringUtils.join(xs, ",");  // カンマ区切り

デバッグとか、文字列結合には便利。
......SQLの構築でこれを使い始めていると、危険シグナルだけど。


ちなみに、JavaScriptではArrayのメソッドにjoinが実装されているのでそれを使える。
文字列を+=でループを回しながら連結するよりは早いはず。

ReflectionToStringBuilder#toString

API - RefrectionToStringBuilder#toString

リフレクションを使って、オブジェクトの中身を全てダンプする仕組みとして、ReflectionToStringBuilderが提供されている。
使い方はtoStringメソッドを呼ぶだけ。出力形式を変更するためのメソッドも提供されている。

  List<String> xs = Arrays.asList("x", "y", "zz");
  // 出力例: "java.util.Arrays$ArrayList@1697b67[a={x,y,zz}]"
  System.out.println(ReflectionToStringBuilder.toString(xs));

こっちはデバッグや実行時ログ出力なんかに便利。
名前の通りリフレクションを使うので、多少パフォーマンスは落ちるけど。

最後に

これぐらいできれば標準実装で欲しかったなあ……
Java7を追い切ってないので、もしかしたら追加されてるかも知れないのだけれど……

*1:先の例はぬるぽ、後の例はfalseを返す