JavaのString、StringBuffer、Charの中でメモリの使用が一番良いものは?

このQ&Aのポイント
  • JavaのString、StringBuffer、Charの中でメモリの使用が一番良いものは?
  • Java初心者です。現在JavaMEのMIDP(2.0)で辞書アプリケーションを作成しています。携帯電話のメモリが小さいことから不向きであると感じていますが、できるだけ多くの単語と説明を登録したいと思っています。
  • Stringは非可変文字列なので、説明内容が変更されるたびに別のメモリを確保します。そのため、メモリ効率が悪いです。一方、StringBufferは可変文字列なので、説明の変更が頻繁にある場合には適しています。また、char配列はメモリ効率が良いですが、扱いがやや複雑になる可能性があります。
回答を見る
  • ベストアンサー

JavaのString、StringBuffer、Charの中でメモリ

JavaのString、StringBuffer、Charの中でメモリの使用が一番良いものは? Java初心者です。 現在JavaMEのMIDP(2.0)で辞書アプリケーションを作成しています。 携帯電話のメモリが小さいことから不向きではあると思っていますが、できるだけ多くの単語と説明を登録していようとしています。 基本的な文法は通常のJavaと同じだと思います。 大まかな構造は不要部分を省きますと、 ----- class Dictionary extend Canvas(){  int i,j,start=0,end=0,x=1;  private static Font fontL=Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_LARGE);  void paint(Graphics g){   //getsetsumei(x)で単語の意味・説明をString型で受け取っています。   //substringで一文字ずつ増やしながら文字の横幅をgetWidthで受け取り、   //描画画面横幅の最大値240を越えないように部分文字列で表示しています。   //文字の続きは文字サイズの縦幅をfontL.getHeight()で取得し、   //改行のような形で続けて表示します。   //また描画画面縦幅の最大領域getHeight()を越えて表示しないために   //i行目までに描画した文字列の縦幅の総和がこれを越えないようにすることで、   //無駄な描画をしないようにしています。   for(i=1;i!=0 && i*fontL.getHeight()<getHeight()-130;i++){//画面縦幅の描画範囲の判定    while(fontL.stringWidth(getsetsumei(x).substring(start,end+1))<240){//画面横幅の描画範囲の判定     end++;//横幅に達するまで文字数を増やす     if(end==getsetsumei(x).length()){//表示すべき文字列の取得が終わった      g.drawSubstring(getsetsumei(x),start,end-start,0,130+x,Graphics.TOP|Graphics.LEFT);      i=-1;//終了条件のi!=0を満たさなくするため      break;     }    }    //描画すべき文字列の一部をSubstringで描画    g.drawSubstring(getsetsumei(x),start,end-start,0,130+y,Graphics.TOP|Graphics.LEFT);    start=end;//次の行の描画すべき部分文字列の開始位置を指定    y+=fontL.getHeight()+1;//改行のためのy座標の移動   }  }  String getsetsumei(int DicNum){   switch(DicNum){   case 0:return " ";//説明無し   case 1:return "辞典,辞書,字引";//Dictionaryの意味、説明   }  } } ----- となっています。 実際は単語の意味をString型で返すgetsetsumeiの引数xの値を変化させて単語に合わせて意味を取得しようとしています。 改行するプログラムのためにgetsetsumei関数は何度も呼ばれることになるので、できるだけメモリを使用せず、高速にしたいと思っています。 色々調べたところStringは非可変文字列であるとのことでした。 これは説明内容が変更されるたびに別のメモリを確保するということでしょうか? それとも同じメモリに新しい説明が上書きされるのでしょうか?その場合、StringではなくStringBufferを使用すべき、もしくはchar配列を使用すべきでしょうか? どなたかご教授願います。

  • Java
  • 回答数2
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

「String型のオブジェクトが不変」ということの意味を勘違いされていると思います。オブジェクトの中身とオブジェクトへの参照を区別してください。不変なのはオブジェクトの中身のほう。 下記のようなコードで変数setsumeiはString型オブジェクトへの参照を保持しているだけなので、実行しても変数setsumeiが保存されているメモリが毎回確保されるなどということはなく、同じ場所が上書きされます。 String setsumei; setsumei=getSetsumei(1); setsumei=getSetsumei(2); setsumei=getSetsumei(3);

HisanaEXE
質問者

お礼

ようやく意味がわかりました! 度々の回答ありがとうございました。

その他の回答 (1)

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.1

> while(fontL.stringWidth(getsetsumei(x).substring(start,end+1))<240){//画面横幅の描画範囲の判定 >     end++;//横幅に達するまで文字数を増やす >     if(end==getsetsumei(x).length()){//表示すべき文字列の取得が終わった >      g.drawSubstring(getsetsumei(x),start,end-start,0,130+x,Graphics.TOP|Graphics.LEFT); xが変わらなければgetsetsumei(x)の結果も変わらないのに、このメソッドを繰り返し呼ぶのは非常に無駄です。以下のように一度Stringの変数で受ければ繰り返して呼ぶ必要がなくなります。 String setsumei=getsetsumei(x); while(fontL.stringWidth(setsumei.substring(start,end+1))<240){     end++;     if(end==setsumei.length()){//表示すべき文字列の取得が終わった      g.drawSubstring(setsumei,start,end-start,0,130+x,Graphics.TOP|Graphics.LEFT);

HisanaEXE
質問者

お礼

回答ありがとうございます! String型の変数に違う値を代入すると、変更不可能なので違うメモリに値が格納される という前提でできるだけString型の変数を使わないようにしていたのですが、 そういうことはないということでしょうか?

関連するQ&A

  • Stringとは一体何だ?

    Stringは型なのでしょうか?それともクラスなのでしょうか? Stringは参照型の型で、クラスを表す、つまり文字列を表す参照型の型であり文字列を表すクラスでしょうか?説明が悪くてごめんなさい。Java歴二週間です。

    • ベストアンサー
    • Java
  • String型とchar型の変換エラーです

    今晩は!またまたこの掲示板にきました。よろしくお願いします。 文字列かブランクを取り出すコードを書きましたが、 -------- char ch_check = str.charAt(i+1) ; if(ch_check ==" ") { --------- のところでString型とchar型の混合は受け入れられませんのようなエラーが出ました。 if(ch_check ==" "をboolean型でうけるのも拒否されました。 どこをどのようにしてやればよいでしょうか。 JAVA初心者です、特に文字列の取り扱いは評判通りわかり難くくないています。 よろしくお願いします。 ---------- public class Mojiretu_Blank { public static void main(String[] args) { String str = "This is a pen."; int i = 1 ; int blank_count = 0 ; while( i < (str.length()+1) ) { char ch_check = str.charAt(i+1) ; if(ch_check ==" ") { blank_count ++ ; System.out.println(ch_check); } else{} System.out.print("ブランクの数は" + blank_count + "個です。"); } } }

    • ベストアンサー
    • Java
  • java 問題

    public static void main(String[] args) { 1 文字列型変数 word をせんげんする String word = "abc"; 2  // 文字列型の変数が入る配列 words を宣言する   // 同時に、word から substring で取り出した文字をセットする Java初心者です。 2番が分かりません。どなたか解説していただけると助かります。

    • ベストアンサー
    • Java
  • 半角カナの文字列操作について

    通常10桁の半角カナの文字列があった場合下記のように String i = "イイイイイイイイイイ"; i.substring(0,5) + ","+i.substring(5,10) Systemout.println(i); として結果を イイイイイ イイイイイと文字列を分割しているのですが 10桁の文字列を半分に区切ろうとした場合 6文字目に濁点が存在した場合 String i = "イイイイバイバイ"; i.substring(0,5) + ","+i.substring(5,10) 結果が イイイイハ ゛イバイ と バの濁点とハが分割されてしまいます。 この半角カタカナの文字列でこの現象を 回避するために 文字列の中で濁点がヒットした場合 文字列の濁点を含んだ文字列の前か後ろで イイイイ ハ゛イバイ もしくは イイイイハ゛ イバイ のように 分割させたいのですがなにか良い方法はありませんでしょうか?? どうぞよろしくお願いします。

    • ベストアンサー
    • Java
  • PHPのGD系の関数で描画した文字列の下に下線を引きたい

    PHPのGD系の関数で描画した文字列の下に下線を引きたい PHPのGD系の文字列関数がありますよね? (例:日本語が扱えるやつだとImageTTFTextとか) これで文字列の長さに揃えてリンクっぽく見せるために 下線を引きたいのですが、良い手法が思いつきません。 文字数をstrlenでカウントしてフォントのサイズ/2を掛けたら 文字列の長さになるかなーと思って試しましたが、 これだとaとあの文字の横幅が違うようにずれが出ます。 あるフォントである文字列描画関数を使ったときに文字列の横幅が 調べられるような手法があれば、その長さに応じた下線が引けるのですが、 そうした手法はないでしょうか?

    • ベストアンサー
    • PHP
  • C#でピクチャーボックスへの文字列描画について

    C#でピクチャーボックスへの文字列描画について DOBON.NETからコピペです //PictureBox1のGraphicsオブジェクトを取得 Graphics g = PictureBox1.CreateGraphics(); string drawString= @"智に働けば角が立つ。情に棹させば流される。 意地を通せば窮屈だ。とかくに人の世は住みにくい。"; //Fontを作成 Font fnt = new Font("MS ゴシック", 12); //文字列を表示する範囲を指定する RectangleF rect = new RectangleF(10, 10, 100, 200); //rectの四角を描く g.FillRectangle(Brushes.White, rect); //文字を書く g.DrawString(drawString, fnt, Brushes.Black, rect); //リソースを開放する fnt.Dispose(); g.Dispose(); 自分で使ってるピクチャーボックスは動的生成してるので picbox[i] という感じになってます この場合 初めの宣言の時は picbox = new System.Windows.Forms.PictureBox[pic_cnt]; for (i = 0; i < n) { picbox[i] = new System.Windows.Forms.PictureBox(); Graphics g = picbox[i].CreateGraphics(); <中略> } で大丈夫なのでしょうか? 文字列は描画されないし、エラーもでないので どこが間違っているのかわかりません… 説明不足のところがあれば書いてください あと、修復場所を指摘してくださればありがたいです

  • Stringからconst char配列への代入

    ランダムな文字列が書かれているtestPrivate.key というファイルがあります。 (ファイル内容) -----BEGIN TEST PRIVATE KEY----- MIIEpAIBAAKCAQEAxjvazMLAylmhH4+9HI0Gbb7WuQAaEVo4VofQQ0T2mshmbXfV xwBb0SeSEm7B38rRgJGCiZtaKI0dzlykdQU04MN2iHQpEd5TWqnWMzqS+reUZhmF (中略) yC/KZMqqr/b1TnbMzQvN/d6G3BXYlb8VOhF88xVY9NhhvcaBv7zLF0+PlC7O1CnM ckqLSKa+yrI85HfkO7mXjWwDecPcNbl8F9hKkYLztQHaafB3ej2jUA== -----END TEST PRIVATE KEY----- この文字列を const char* Client_private; この配列に代入するにはどのようにすれば良いでしょうか? 現在次の様なプログラム関数を作った時に、 bool testPrivateKey(fs::FS &fs, String path) { //File file = SD_MMC.open(path, "r"); File file = fs.open(path, "r"); if (!file) { Serial.printf("Can't Open File %s", path); return false; } String keygenComplete; String keygen; while (file.available()) { String line = file.readStringUntil('\n'); line = line.substring(0, line.indexOf('---')); keygen = line.substring(0, line.indexOf('\n')); keygen.trim(); keygenComplete += keygen; } Client_private = keygen.c_str(); Serial.printf("data check: %s\n", Client_private); //Serial.printf("data check: %s\n", keygenComplete.c_str()); return true; } この関数を testPrivateKey(SD, "/private.pem.key"); これで呼び出した時のシリアルモニタの結果は data check: このような感じでkeygenCompleteで貯めたはずの文字列が表示されませんでした。 なお、 関数内でコメントアウトしている Serial.printf("data check: %s\n", keygenComplete.c_str()); これを戻して testPrivateKey(SD, "/private.pem.key");を実行した場合は、 data check: MIIEpAIBAAKCAQEAxjvazMLAylmhH4+9HI0Gbb7WuQAaEVo4VofQQ0T2mshmbXfVxwBb0SeSEm7B38rRgJGCiZtaKI0dzlykdQU04MN2iHQpEd5TWqnWMzqS+reUZhmFYFFaX/gDh4ECs7j1f6DpRtO (中略) rI85HfkO7mXjWwDecPcNbl8F9hKkYLztQHaafB3ej2jUA== このファイルの文字列が出てくるので、”keygenComplete”には文字列は入っていることは確認できました。 適切な代入方法など、ご教示の程よろしくお願い致します。

  • Javaで素数の表を表示させたいのですが、うまく表示されません(>_<)

    以前、Javaで素数の表を作ろうと、ここ↓ http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1432689724 で助けをお願いし、数名の方からご回答をいただきました。 「うまく書けません」という曖昧な事を言ってしまい、申し訳なかったと思います。 とりあえず、書いてくださったコードを一字一句理解することから始めようと思い、回答してくださったある方のプログラムを実行してみました。 (「Sosuu→sosuu」とだけ変更しました。) ---------------- import java.awt.*; import java.awt.event.*; public class sosuu extends Frame { static final int N=200; int k,x,y; // (x,y) は 数字の表示位置 public sosuu() { setTitle("エラトステネスの篩(ふるい)により素数を求める"); setLocation(170,0); setBackground(Color.WHITE); //画面を閉じるための処理 addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } public void paint(Graphics g) { Font f=new Font("MS 明朝",Font.BOLD,12); g.setFont(f); // フォントの設定 g.setColor(Color.red);// 数字を赤で表示 //初めはすべて赤字で表示 for (int i=0; i<20; i++) { for (int j=1; j<=10; j++) { x=10+50*j; y=100+i*25; int k; k=10*i+j; // 数字を揃えて表示するための操作 // subString(int beginindex, int endindex)は部分文字列を返す // beginindexは取りだす最初の文字位置、endindexは取りだす最後の文字位置 String str = " "+k; str =str.substring(str.length()-4,str.length()); g.drawString(str,x,y); } } //素数でないものを青字で表示 k=(int)Math.sqrt(N);// N までの素数を求めるとき, sqrt(N)までの数の // 倍数であるかどかを調べれば十分 g.setColor(Color.blue);//素数でない 数を青で表示 String str = new String(); //1は素数でないので除く str = " 1"; str =str.substring(str.length()-4,str.length()); g.drawString(str,60,100); for (int i=2; i<=k; i++) { int n=i; //iの整数倍 int nn=0;//iの倍数を作るのために while(n<=N){//N以下の時続ける x=60+50*((n-1)%10); //横の位置 y=100+25*((n-1)/10);//縦の位置 //初めてでてきた数値は素数、それ以外は素数でない if(n != i){ str = " "+n; str =str.substring(str.length()-4,str.length()); g.drawString(str,x,y); } n=i*(++nn); } } } public static void main(String[] args) { //インスタンスの生成 sosuu so=new sosuu(); //画面のサイズ so.setSize(630,650); //描画(つまりpaint()を呼ぶ) so.setVisible(true); } } ---------------- を、Eclipse(3.2.2)に貼り付けて、「実行→実行→Javaアプリケーション」で、アプレットを起動させてみました。 すると、何も表示されない真っ白な画面が出てきたのです(ToT) コードのどこかが間違っているのでしょうか? エラーがあると、豆電球にバッテンマークみたいなものが表示されると思うのですが、特にそういったものは表示されません。 何が原因で、アプレットを起動しても真っ白な画面しか出てこないのか、ご教授いただければ幸いです(>_<) よろしくお願いします<m(__)m>

    • ベストアンサー
    • Java
  • プロポーショナルフォントで文字列の縦幅横幅

    JTextPane中のプロポーショナルフォントの文字列の表示上の横幅及び縦幅をpixel単位で取得したいです。 ここで言う文字列とは空白文字・タブ文字・改行文字を含まない一続きの文字列を指します。 どの様な方法がありますでしょうか? 同時に、JTextPaneの入力領域左端から文字列の書き始めまでの距離(pixel)の取り方もお教えいただけると助かります。 どうか宜しくお願いします。

  • Java 電卓を作っているのですが・・・

    こんにちは。 趣味でプログラミングをしているものです。 Java で電卓を再現しようとしていて、 コーディングが終わり動作を確認しているのですが、 わからないところがあるので質問させていただきました。 よろしくおねがいします。 平方根を求めるときなのですが、3や5などはある程度正確に求められている と思うのですが、 平方根を求めたとき整数になるもの 例えば9などは小数のまま表示されてしまいます。 電卓で表示され得るすべての実数について平方根を求めるには ニュートン法がよいと思うのですが・・・ 二点ほど質問させていただきます。 ------------------------------------ 質問A まず、BigDecimal型の平方根を求めて、 その toString() から得られた文字列を メソッドvalidControl( String value ) に渡すのですが その冒頭で末尾から先頭方向に続く'0' の列を取り除きたいのですが そのために、変数の中身をみてみたのがこの質問の下部のほうにある (ア) (イ) です。 sqrt(() などの演算結果でえられた文字列のうち 信頼できる範囲以下の文字列を validControl で切り取りたいのですが プロが実際に電卓を作るとしたら、 どのような処理になるのでしょうか? ------------------------------------ 質問B 平方根を求めるメソッドsqrt 内で二分法の処理では 除算のスケールを 64 に指定していますが、 実行結果(ア)(イ)の文字列の長さが異なるのは なぜでしょうか? ------------------------------------ private BigDecimal sqrt( BigDecimal value ) { BigDecimal two = new BigDecimal( "2" ); BigDecimal x = value.divide( two ); BigDecimal last_x = BigDecimal.ZERO; BigDecimal gap = x.subtract( last_x ); BigDecimal range = BigDecimal.ONE.movePointLeft( 64 ); BigDecimal t; while( gap.compareTo(range) > 0 ) { last_x = new BigDecimal( x.toString() ); //t = value.divide( x, 64, BigDecimal.ROUND_DOWN ); //(イ) //test statement t = value.divide( x, 64, RoundingMode.UP ); // (ア) // x = x.add( t ).divide( two ); gap = x.subtract( last_x ).abs(); } return x; } -------------------------------------- private String validControl( String value ) throws KETAException { String retstring = ""; boolean overflag = false; int idx1 = value.indexOf( '.' ); int gap = 0; int seisu_length = 0; // 整数部分の文字列の長さ int len = value.length(); int start = len-1; int idx2 = start; System.out.println( "(0)" + value ); System.out.println( "(1)" + String.valueOf( start ) ); while( value.charAt( idx2 ) == '0' ) { idx2 --; } if( idx2 != start ) { value = value.substring( 0, idx2 + 1 ); len = value.length(); } System.out.println( "(2)" +String.valueOf( idx2 ) ); // 以下省略 -------------------------------------- (ア) を実行したときの結果 (0) 3.000000000000000000000000000000000000 00000000000000000000000000000546875 (1)72 (2)72 --------------------------------------- (イ) を実行したときの結果 (0) 2.999999999999999999999999999999999999 999999999999999999999999999996875 (1)70 (2)70 -------------------------------------- 長文になり申しわけありませんが ご存知のかた教えていただけないでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java