北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

Stringのコンストラクタ

Java EE勉強会のポジペのネタです。

import java.util.*;

class Main{

    // 1MBのサイズのStringを作る
    static String makeHugeString(){
        StringBuilder buf = new StringBuilder();

        for(int i = 0 ; i < 1000000; i++){
            buf.append(i % 10);
        }

        return buf.toString();
    }


    static public void main(String[] args){
        List<String> list = new ArrayList<String>();
        int cnt = 0;

        while(true){
            // 巨大な文字列を得る
            String data = makeHugeString();

            // 先頭文字だけを集める
            list.add(data.substring(0, 1));            

            if(++cnt % 10 == 0) System.out.println(cnt);
        }
    }
}

【結果】
$ java Main
10
20
30
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

Listにsubstring()の結果を集めているのですが、30文字程度集めただけでヒープがいっぱいいっぱいになってしまいます。これはsubstring()の実装が内部ポインタだけを移動することで実現しているからです*1

// 先頭文字だけを集める
list.add(new String(data.substring(0, 1)));            

と変えると大丈夫になります。これは、String(String)コンストラクタが、ポインタと内部表現の正規化を行っているためです。

ただ、こいつはドキュメントには書かれてない動きなので、積極的に使うべきではないと思います。今後のリリースでどうなるかわかりませんし≧(´▽`)≦。

*1:少なくともTigerでは。今後は知らん。