Java 拡張for文でMapをループする方法

Mapをループするとき、entrySetを忘れるのでメモ。

        for (Entry<String, String> entry : map.entrySet()) {
            // 拡張for文でMapをLoopする

            // キーを取得する。
            String key = entry.getKey();
            // 値を取得する。
            String value = entry.getValue();

            System.out.println(key + " : " + value);
        }

Java trim 全角スペースは範囲外

ロジック側でスペースをTrimするなんてのはよくある話。
Javaの標準メソッドでは、半角スペースしかTrimされないので、要注意。

標準Trimにしてくれればいいのにね。

public static String trim2(String str) {
    if (str == null || str.length() == 0) {
        return str;
    }
    int st = 0;
    int len = str.length();
    char[] val = str.toCharArray();
    while ((st < len) && ((val[st] <= '\u0020') || (val[st] == '\u00A0') || (val[st] == '\u3000'))) {
        st++;
    }
    while ((st < len) && ((val[len - 1] <= '\u0020') || (val[len - 1] == '\u00A0') || (val[len - 1] == '\u3000'))) {
        len--;
    }
    return ((st > 0) || (len < str.length())) ? str.substring(st, len) : str;
}

【Java】文字列の前後から半角と全角の空白スペースを除去する方法

try-with-resources

tryと言ったらcatch。

catchと言ったらfinally。

所謂Java的常識が、また変わるのか。

今度はtry-with-resources。

finally句の使用は、主にリソースの解放等に使われている。

tryはresourcesと共に・・・。そういうことか!

今までのリソース解放はこんな感じだったはず。

// JavaSE6
// Connectionを解放する。
Class.forName("ドライバ名");
Connection conn =
        DriverManager.getConnection(
            "URL",    //URL
            "ユーザ名",     //ユーザID
            "パスワード"    //パスワード
        );
try {
    // なんか色々処理
catch (Exception e) {
    System.err.println(e.getMessage());
} finally {
    // コネクションをクローズ
    if(null != conn) {
        conn.close();
    }
}

Connection.close()メソッドでもtry-catchしたかな?

それを、こうできる。

// JavaSE7
// Connectionを解放する。
Class.forName("ドライバ名");
try (Connection conn =
        DriverManager.getConnection(
            "URL",    //URL
            "ユーザ名",     //ユーザID
            "パスワード"    //パスワード
        )){
    // なんか色々処理
catch (Exception e) {
    System.err.println(e.getMessage());
}

これで解放されるらしい。

Connectionはされないのかな?そこはまた調べよう。

AutoCloseableというインターフェースの機能が発動するらしい。

独自クラスだと、上記を実装すればいい。

public class Sample implements AutoCloseable {
    /**
     * Sampleクラスのリソース解放処理
     */
    @Override
    public void close() throws Exception {
        // ここにリソース解放の処理を記載
    }
}

リソース解放を意識しなくて済むってことかな?

例外処理発生時にどうするかとか、考えながら実装しないとね。

まだよくわかってないので、また勉強しようっと。

数値リテラルってなんだ。

JavaSE7で新しい機能が備わった。
それは数値リテラルだ。

バイナリリテラルと、アンダースコアリテラル。
それぞれを説明できるようになろう。

バイナリリテラル
簡単に言うと、可読性の向上が期待されているのかな?
2進数表記をソースコードで表現して良いようになったのだ。

// JavaSE6の場合
byte b1 = (byte)21;

// JavaSE7の場合
byte b2 = 0b10101;

なるほど。2進数表記になると、確かにわかりやすいかも。
データ通信とかが固定長だったりした場合に役立つのかな?

アンダースコアリテラル
これは一体なんなんだ。
数値に意味を持たせるためのもの??
う~~~ん、よくわからんぞ。

// JavaSE6の場合
int i = 11111;

// JavaSE7の場合
int j = 1_1_1__1___1;

ん?絵文字か?
コンパイル時には読み飛ばされるらしい。
数値に意味を持たせるには、確かにアンスコ使えればいいけど、実用方法がわからない。

使えそうな時があれば使ってみよう。

SwitchでStringを!?

今まで、JavaではStringを判定するときに色々苦労した。
一番ダサいやり方は以下の様にコードを書いている。

public class SwitchToStringJavaSE6 {
    /**
     * Stringの分岐は今までこうだった。はず。。。
     */
    public static void main(String[] args){
        String target = "TRUE";

        // "TRUE"を判定する
        if ("FALSE".equals(target)) {
            System.out.println("FALSE");
       } else if ("DEFAULT".equals(target)) {
            System.out.println("DEFAULT");
       } else if ("TRUE".equals(target)) {
            System.out.println(target);
       } else {
            System.out.println("NOTARGET");
       }
    }
}

これで”TRUE”を判定し、”TRUE”と表示していた。
しかし、JavaSE7ではなんとSwitchでStringも使えるようになった。。。
ウソだろ。。。

public class SwitchToStringJavaSE7 {
    /**
     * JavaSE7のステキなSwitch文
     */
    public static void main(String[] args) {
        String target = "TRUE";
        // Switch文でStringを判定する。
         switch(target) {
            case "FALSE":
                System.out.println("FALSE");
                break;
            case "DEFAULT":
                System.out.println("DEFAULT");
                break;
            case "TRUE":
                System.out.println(target);
                break;
            default:
                System.out.println("NOTARGET");
                break;
         }
    }
}

これで”TRUE”が表示される。

これって・・・。
新人がよく間違えるSwitch文じゃないかしら・・・。
StringはSwitch使えないんだよ!って教えられた気がする。

どういう原理????
JavaSE6で書くと、こういうことらしい。

public class SwitchToStringJavaSE6Reproduce {
    /**
     * JavaSE6でJavaSE7のSwitchを再現する。
     */
    public static void main(String[] args) {

        String target = "TRUE";
        // ハッシュコード判定用
        int hash = -1;

        switch (target.hashCode()) {
        // ハッシュコードの確認を行う。
        case 66658563:
            // "FALSE"のハッシュコード
            if ("FALSE".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 0;
            }
            break;

        case -2032180703:
            // "DEFAULT"のハッシュコード
            if ("DEFAULT".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 1;
            }
            break;
        case 2583950:
            // "TRUE"のハッシュコード
            if ("TRUE".equals(target)) {
                // ハッシュコードが同じ文字列を考慮
                hash = 2;
            }
            break;

        }
        // 判定後の処理をさらに記載する。
        switch (hash) {
        
        case 0:
            System.out.println("FALSE");
            break;
        case 1:
            System.out.println("DEFAULT");
            break;
        case 2:
            System.out.println("TRUE");
            break;
        default:
            System.out.println("NOTARGET");
        }
    }
}

なるほど。こういう手があったか。。。
でも、これは自動コンパイルの中で実施してもらわないと、やっぱり使えないな。。。
というわけで、JavaSE7は上記のようなめんどくさいことをやってくれるおかげでSwitch文でStringが使えるわけだ。

ありがとう。JavaSE7。

ちなみに、問題もある。

switch(null) { // コンパイルエラー
case null;  // コンパイルエラー
    // 省略
}

じゃあ、これはどうだ。

String target = null;
switch(target) {  // NullPointerExceptionが発生
case "TEST":
    // 省略
}

null.hashCode()を実施してNullPointerExceptionが発生する。
ということは、StringのSwitch文の前には必ずnullチェックを付けたほうが良いみたい。

使い方はそれぞれだが、凄く活用できそうな拡張であることがわかった。