優雅なプログラミングで文字の性能を考えると、あなたは「正常」になります(二十二)


嬉しそうに笑う
【夕食を食べてリビングで新聞を読んで、奥さんに「茶碗を洗ったの?」と聞いた.奥さんはまじめに言った.「旦那さん、そう聞くべきだ.ベイビー、茶碗を洗ってあげよう.それから、旦那さん、もう洗ったよ.これでいいのに.」そこで、旦那さん:ベイビー、茶碗を洗ってあげよう.奥さん:うん、行こう.】
質問を出す
プロジェクト内の文字列操作で注意すべきパフォーマンスの問題は何ですか??
問題を解決する
以下は『Javaプログラム性能最適化』という本の中の少しの総括と、自分の考えから来て、どの文章も短くて、あまり書くのが好きではありません.一歩一歩ゆっくり勉強すればいいです.
Stringクラスの基本的な実装:char配列、offsetオフセット量、Stringのcount長
Stringの最適化は主に3つの面に現れ、Stringオブジェクトの3つの特徴でもある.
  • 不変性:Stringオブジェクトが生成されると、変更することはできません.
  • 定数プールの最適化.
  • クラスのfinal定義.

  • 例1:
    @Test
    public void testString(){
        String boy = "boy";
        String girl = "girl";
        String girl2 = "girl";
        String girl3 = new String("girl");
        System.out.println(boy == girl);//false
        System.out.println(girl == girl2);//true
        System.out.println(girl == girl3);//false
        System.out.println(girl == girl3.intern());//true
    
    }
    

    subStringメモリリークの問題
    具体的には、上級者の文章を見ることができます.
    http://www.cnblogs.com/techyc/p/3324021.html
    jdk 6ではsubstringは元の文字列を指し、new String(str.substring()でメモリ漏洩を回避できますが、jdk 7ではこの問題はありません
    文字列の分割と検索
    より効率的なStringTokenizerクラスを使用して文字を分割
    例2:
    @Test
    public void testString(){
    
        String originalStr = null;
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<10000;i++){
            sb.append("ay");
            sb.append(";");
        }
        originalStr = sb.toString();
    
        long startTime = System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            //     10000 
            originalStr.split(";");
        }
        System.out.println(System.currentTimeMillis() - startTime);
    
    }
    

    結果費:1492ms(私のパソコン比較lan)
    性能改造:
    @Test
    public void testString(){
        String originalStr = null;
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<10000;i++){
            sb.append("ay");
            sb.append(";");
        }
        originalStr = sb.toString();
        long startTime = System.currentTimeMillis();
    
        StringTokenizer tokenizer = new StringTokenizer(originalStr,";");
        for(int i=0;i<10000;i++){
            while (tokenizer.hasMoreTokens()){
                tokenizer.nextToken();
            }
        }
        System.out.println(System.currentTimeMillis() - startTime);
    }
    

    結果費:8 ms(私のパソコンはlanを比較します)これは1つの等級ではありません!getを上げる
    効率的なcharAt()メソッド
    charAt()はstartsWith()やendsWith()よりも効率が高く、単一文字の先頭を判断するのにはまあまあですが、複数についてはテストしてみましたが、効率はそれほど高くありませんでした.
    例3:
    @Test
    public void testString3(){
    
        String loveStr = "Love you!!!";
        long startTime = System.currentTimeMillis();
        //  100  
        for(int i=0;i<1000000;i++){
            //     L  
            if(loveStr.charAt(0) == 'L'
                    ){
            }
        }
        System.out.println(System.currentTimeMillis() - startTime);
    }
    

    結果費:20 ms
    @Test
    public void testString4(){
    
        String loveStr = "Love you!!!";
        long startTime = System.currentTimeMillis();
        //  100  
        for(int i=0;i<1000000;i++){
            //     L  
            if(loveStr.startsWith("L")){
            }
        }
        System.out.println(System.currentTimeMillis() - startTime);
    }
    

    結果費:27 ms
    StringBufferとStringBuilder
    Stringオブジェクトは可変オブジェクトであるため、文字列を変更する必要がある場合、文字列接続、置換など、Stringオブジェクトは常に新しいオブジェクトを生成するため、パフォーマンスが相対的に低下します.
    例4:
    String love = "999  " + "999  " + "999  " + "999  ";
    

    および
    StringBuilder result = new StringBuilder();
    result.append("999  ");
    result.append("999  ");
    result.append("999  ");
    result.append("999  ");
    

    Java仮想マシンはString接合の性能を最適化するためです.複数の接続操作の文字列を、コンパイル時に個別の長い文字列に合成します.だから上の2つは効率が悪い.
    両者の性能はそれほど悪くないが,コンパイラによるプログラムの最適化ではなく,コードの実装においてStringBuilderまたはStringBufferをできるだけ使用することを提案した.
    例5:
    // 1
    for(int i=0;i<10000;i++){
        str = str + i;
    }
    
    //                ,          StringBuilder  ,       
    for(int i=0;i<10000;i++){
        str = (new StringBuilder(String.valueOf(str))).append(i).toString();
    }
    
    // 2
    for(int i=0;i<10000;i++){
        result = result.concat(String.valueOf(i));
    }
    
    // 3
    StringBuilder sb = new StringBuilder();
    for(int i=0;i<10000;i++){
        sb.append(i);
    

    ` }
    上記の3つの方法の効率(低から高へ):
    1 < 2 < 3
    

    Java仮想機会Stringの加算操作を最適化するが、コンパイラはまだ頭が悪い.
    StringBufferとStringBuilderの選択
    StringBufferとStringBuilderは双子の兄弟です.
    StringBuilderの効率>StringBufferの効率
    StringBuilderは非スレッドで安全です.StringBufferはスレッドが安全です.
    一陰一陽の道は、どこにでも現れている.
    本を読んで悟る.
    張小?の『パンの木の上の女』から
  • 感情を忘れようとする方法は永遠に一つしかない:時間と新歓.もし时間と新歓もあなたに感情を忘れさせることができないならば、原因はただ1つだけあります:时間が足りなくて、新歓が足りません.
  • 私は青春を彼に投資して、彼は成功して、別の女性を爱するかもしれません.彼は失敗したので,私は何も持っていない.爱情はあまりにも頼りにならないで、事业だけが1部の努力の1部の収获で、私は自分の事业があると思っています.
  • あなたを身の回りに残すことができなくて、あなたの過ちではありませんて、私の失敗です.あなたがかつて私を爱したあれらの短い歳月の中で、私はもしかすると世界で最も幸せな人で、ただあれらの日はすでに过去になって、残しても残すことができません.私は爱が乞うことができないことを知っていて、もし私があなたのために1つのことをすることができたら、待つことです.
  • 一人の男が、泥足で彼を爱していない女を爱して、自尊心を放弃する運命にある.
  • 爱のためにしたことはすべて悪いことではありません.
  • その時、私はすでに知っていて、1人の女性として、あなたはとても優れているほうがいいですか、あるいはとてもきれいです
  • その他
    もしあなたに少しの楽しみを持ってきたら、楽しみを伝え続けて、転載を歓迎して、いいね、トップ、貴重な意見を残して、支持に感謝します!