String[][][] arg = = new String[x][x][x];
でxが638の時にjava.lang.OutOfMemoryErrorになってしまいます。
VM起動時のヒープ最大値は1GBまで試しましたがダメでした。

このときargオブジェクトはどれだけのメモリを必要とするのでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (4件)

このnewで作られるオブジェクトは、配列オブジェクトだけです。

Stringオブジェクト自体は作られません。
なので、オブジェクトのサイズとしては、配列オブジェクトのサイズだけを考えればよいことになります。
(ちなみに、メソッド本体はクラスに1つあるだけで、作成したオブジェクトの数だけできるわけではないですから、オブジェクトを作ると、新たにメソッドの分のメモリが必要になるわけではありません)

さて、argオブジェクトのサイズですが、1つのオブジェクトへの参照を保持するのにまず何バイトが必要か考える必要があります。
32bitのJavaだったら、たぶん32bit=4バイトでしょう。
この配列の要素数はx^3個ですので、1つあたりが4バイトとなると、x^3 * 4 バイトのメモリが最低限必要ということになります。
もちろん、他にも多少メモリが必要でしょうが、xが大きいときのことを考えるわけですし、無視しても問題ないでしょう。

x=638の場合を計算してみると、638^3 * 4 = 1038776288 となります。
これは約990MB で、だいたい1GBです。
ヒープの最大値を1GBで試したということですので、計算と合っているのではないでしょうか。

この回答への補足

回答ありがとうございます。

>32bitのJavaだったら、たぶん32bit=4バイトでしょう。
この回答を示すページ等はありますか?

補足日時:2009/05/12 14:57
    • good
    • 0

論より証拠、ヒープが足りる範囲で実際に測ってみればいいのです。



int n=1000;
Runtime rt = Runtime.getRuntime();
long free1, free2;
System.gc();
free1 = rt.freeMemory();
String[] arg = new String[n];
free2 = rt.freeMemory();
System.out.println("Free diff: " + (free1 - free2));

うちのJava環境では、n=1000のときの結果が4016、n=2000のときが8016でした。このことから、String[]の配列1要素あたり4バイト消費することが分かります。
他のJava環境では違うかもしれません。64ビット環境用のJavaだったら、おそらく1要素あたり8バイトになるでしょう。

なお、上のコードは手抜きです。本当はfreeMemory()だけじゃなくてtotalMemory()の値の変化も確認する必要があるはず。
    • good
    • 0

xが638って、まさかarg[638][638][638]ってことかね?



配列の全要素にStringインスタンスを保管する、ということだな。Stringリテラルではなくて。まぁ、実際にどれだけ使われているかはわからないが、ざっと概算で必要なメモリを計算してみると。

まず、arg[638][638][638]という時点で、259694072個のStringオブジェクトが保管されるだけのメモリが必要になることはわかるだろう。クラスというのは、マジックナンバー、バージョン、コンスタントプール、インターフェイス、フィールド、メソッド、属性リストの各エントリ数などが最低限必要で、全く何も中身がないインスタンスでも既に24byteほどメモリをしめる。完璧に空っぽのインスタンスであったとして、

638×638×638×24 = 6232657728byte = 約5.8GB

と、ざっと6GBほどが必要いうことになる。これは中身が空っぽの状態であって、Stringには実際問題として多数のフィールドとメソッドがあるわけだから、まぁざっとこの10倍として、60GBぐらいか。

これに加えて、個々のString値の保管領域が必要となる。どのぐらいのテキストを保管するかによるが、平均10byte程度の文字列であったとしても数GBは必要になる。実際問題として、100GBぐらいはないと正常に動かすのは難しいかも知れない、という結論になるが。

この回答への補足

回答ありがとうございます。

>全く何も中身がないインスタンスでも既に24byteほどメモリをしめる。
この回答を示すページ等ありますでしょうか?

補足日時:2009/05/12 14:55
    • good
    • 0

>このときargオブジェクトはどれだけのメモリを必要とするのでしょうか?



と言われても・・・

String[][][] arg = = new String[x][x][1];

を実行して消費するリソースの638倍を目安に考えればいいんじゃないですかね(オーバーヘッドや中身については考えていない)
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q実行計画の「COST」と「BYTE」について教えていただきたいです。

実行計画の「COST」と「BYTE」について教えていただきたいです。

書籍には
COST・・・・CBOによって見積もられた操作コスト。
BYTE・・・・アクセスされるバイト数のCBOのアプローチによる見積もり。
と書かれていますが、いまいちピンときません。


私は、
COSTは、検索するテーブルのデータ量が多いほうがコスト値が大きくなる。
BYTEは、検索条件に合致して取得できるデータが多いほうがバイト値が大きくなる。
と思っているのですが、正しいでしょうか?

Aベストアンサー

このあたりを参考にしてください。
COSTはデータ量だけではなく、その表やViewのアクセスに要する時間やSortや結合が必要なら、そのために必要なCPU時間等も考慮されています。
表があるHDDのアクセス速度なんかも考慮されているし、表のエクステントが複数になっているかとかも考慮されています。
書籍はわかりにくいかもしれませんが、嘘は少ないと思います。著者が思い違いをしてないとは言い切れませんが。

参考URL:http://otn.oracle.co.jp/forum/message.jspa?messageID=35016743

QIOException ってどういうときに起こるのでしょうか?

IOException ってどういうときに起こるのでしょうか?

http://www.atmarkit.co.jp/fjava/rensai2/javaent12/javaent12.html
を見て勉強しています。

  catch ( IOException e) {
    System.out.println( "キーボードが故障しているのかもしれません" );
  }

と書いてあります。
ハード(キーボード)が故障しているのを Java のプログラムのレベル(ソフトウェア)で感知できるというのがよくわかりません。「

NumberFormatException の方はわかるのですが・・・

Aベストアンサー

現実的には、キーボードからの入力でIOExceptionが発生することは、
ほとんどあり得ないと思います。
そもそも、キーボードが故障していたとしても、
IOExceptionは投げられないでしょう。
「キーボードが故障しているのかもしれません」というのは、
その記事の著者が冗談で書いたのだと思います。

ではなぜ、try-catchを書かなくてはいけないのか?
InputStreamやBufferedReaderは、
データ入力を抽象化したものだからです。
実際の入力元はキーボードだったり、ファイルだったり、
ネットワーク接続だったりするわけですけど、
InputStreamは、その入力元の情報を持っていないので、
データを読み取る際は常に
IOExceptionをキャッチするコードを書かなくてはいけません。
たとえ、絶対にIOエラーが発生しないストリームだとしても。

さらに付け加えるなら、
そもそも「標準入力=キーボード」であるとは限りません。
(一般的にはキーボードであることが多いですが。)
Javaでは、
System.setIn(InputStream)
を呼び出して、標準入力を変えてしまうことができますし、
標準入力を指定してプログラムを実行することができるOSもあります。

追伸1:
例外をキャッチしたときは、
スタックトレースをプリントすることをおすすめします。
catch (IOException e) {
e.printStackTrace();
}

追伸2:
そのプログラムでIOExceptionを発生させる最も簡単な方法は、
readLine()を呼び出す前に
標準入力(System.in)を閉じてしまうことです。
System.in.close();

現実的には、キーボードからの入力でIOExceptionが発生することは、
ほとんどあり得ないと思います。
そもそも、キーボードが故障していたとしても、
IOExceptionは投げられないでしょう。
「キーボードが故障しているのかもしれません」というのは、
その記事の著者が冗談で書いたのだと思います。

ではなぜ、try-catchを書かなくてはいけないのか?
InputStreamやBufferedReaderは、
データ入力を抽象化したものだからです。
実際の入力元はキーボードだったり、ファイルだったり、
ネットワーク接...続きを読む

Qシンボルが見つかりませんというエラーが理解できません。

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Image[3];
Thread t;
int index1 = 0;
int index2 = 0;
String msg = "";
String msg1 = "";

boolean state = false;
Button b1 = new Button("ぐー");
Button b2 = new Button("ちょき");
Button b3 = new Button("ぱー");

public void init(){
for(int i = 0; i<=2; i++){
img[i] = getImage(getDocumentBase(),"hanabi" + (i+1) + ".JPG");
}
add(b1);
add(b2);
add(b3);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
msg1 = "結果は・・";

}

public void paint(Graphics g){
g.drawImage(img[index1],350,30,this);
g.drawImage(img[index2],695,30,this);
g.drawString("コンピューター",420,300);
g.drawString("あなた",800,300);
g.drawString(msg,630,320);
g.drawString(msg1,550,320);
}

public void start(){
state = true;
t = new Thread(this);
t.start();

}

public void run(){
while(state){
index1++;
if(index1 == 3){
index1 = 0;
}
index2++;
if(index2 == 3){
index2 = 0;
}
repaint();
try {
Thread.sleep(60);
}catch(InterruptedException e) { }
}
}

public void actionPerformed(ActionEvent e){
if(state == false) {
start();
return;

}
state = false;
if(e.getSource() == b1) {
msg = "ぐー";
index2 = 0;
}

else if(e.getSource() == b2){
msg = "ちょき";
index2 = 1;
}

else if(e.getSource() == b3){
msg = "ぱー";
index2 = 2;
}
check();
repaint();
}

public void check() {
if(index1 == index2) msg ="あいこ";


else if (index1 == 0) {
if(index2 == 2) msg="あなたの勝ち";
else msg ="あなたの負け";
}

else if(index1 == 1) {
if(index2 == 0) msg="あなたの勝ち";
else msg="あなたの負け";
}

else if(index1 == 2) {
if(index2 == 1) msg="あなたの勝ち";
else msg="あなたの負け";
}

}
}

以下のようなじゃんけんゲームのプログラムを書いたのですが、「シンボルが見つかりません。」というエラーが表示されるのですが、エラーの意味が理解できず、解決できません。どこが間違っているのか教えていただけませんか。

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.File;

public class janken extends Applet
implements Runnable, ActionListener {
private static final int EXTERNAL_BUFFER_SIZE = 128000;

Image image[] = new Imag...続きを読む

Aベストアンサー

「シンボルを見つけられません。」というエラーの下に何か表示がありませんでしたか?そこにヒントがあると考えられます。
シンボルを見つけられませんといエラーが表示される主な理由は4つあります。
(1)クラス、メソッド、変数などの綴りミスや定義していない変数を使用している可能性がある。
(2)コンストラクタを呼び出すときに、newを忘れている可能性がある。(3)公開されていないメンバーを呼び出している可能性がある。
(4)必要なimport文を記述し忘れている可能性がある。
ここでのあなたのエラーは(1)番ではないでしょうか?上記ではimageとなっている変数がimgになっていますね。
これはエラー表示をよく見ることで意外と簡単に解決できるのです。
ゆっくり丁寧にエラー表示を見るように心がけることが大事ですよ。

QJavaには、構造体はないんですか?

 C言語の構造体みたいなのはないんですか?

野球のデータを扱っているのですが、構造体がないのでできません。

打率の順位をソートしたいのですが、Cでは構造体でソートすれば選手名まで全部ソートできたのですが。。。

Javaでは、いちいち選手名、打率などの配列を作っているのですが、打率をソートしてから選手名と一緒に表示しようとしても打率の配列だけ、ソートしてあり選手名の配列と打率の配列があいません。

要するに、打率の配列はソートし、選手の配列はデータを入力したときのままなので、順番が違っているのです。

うまい方法を教えてください。初歩的な質問でごめんなさい。

Aベストアンサー

メンバーが public なクラスが構造体と(ほぼ)同じです。

大体こんな感じ。

// sort Object using Arrays.sort()

import java.util.Arrays;

class Batter implements Comparable {
 public double rate;
 public String name;
 Batter(double r, String n) {
  rate = r;
  name = n;
 }
 public int compareTo(Object o) {
  return (int)((rate - ((Batter)o).rate)*1000.);
 }
}

class w03 {
 public static void main(String[] args) {
  Object[] batter = {
   new Batter(0.3, "ichiro"),
   new Batter(0.1, "shinjo"),
   new Batter(0.0, "irabu")
  };

  // sort
  Arrays.sort(batter);

  // print-out to console
  for (int i=0; i < batter.length; i++) {
   Batter b = (Batter)batter[i];
   System.out.println(b.name + " " + Double.toString(b.rate));
  }
 }
}

このように java.util.Arrays の sort() メソッドを使うと、C でやってた
イメージに近くなります。

C の qsort() と違って、どんなデータでもソートできるわけではなく、対象と
なるクラスは Comparable インターフェースを実装しなくてはいけません。

メンバーが public なクラスが構造体と(ほぼ)同じです。

大体こんな感じ。

// sort Object using Arrays.sort()

import java.util.Arrays;

class Batter implements Comparable {
 public double rate;
 public String name;
 Batter(double r, String n) {
  rate = r;
  name = n;
 }
 public int compareTo(Object o) {
  return (int)((rate - ((Batter)o).rate)*1000.);
 }
}

class w03 {
 public static void main(String[] args) {
  Object[] batter = {
...続きを読む

QJavaのメモリの管理

なんか基本的なことなんですけど、ちゃんと把握していないなーと思って質問します。

staticメソッドを使用してしまうと、メモリ上に残ってしまうからあまり使うななどとよく言うと思います。これに対して、staticでないメソッドは使用されている間はstaticと同じように管理され、使用後に開放対象となるということなのか。というか、非staticメソッドは、2箇所から同時にアクセスされたらメソッド2つ分のメモリを使用するのか。その前に、staticメソッドであっても、同時に2箇所からアクセスされたら2つ分のメモリを消費するはずではないのか。

サーブレットでは、アクセスのあったサーブレットクラスがインスタンス化され、そのインスタンスが何度も使い回される、との記述を見たが、複数のアクセスがあったときに同時に処理ができるが、これは実質メモリ上に複数のメソッドが存在することにならないのか…

ロードの際にはクラス単位で読み込まれるのか、メソッド単位なのか。staticメソッドと非staticメソッドが混在しているクラスでは、読込み、開放はメソッド単位で行っているのか。

などの疑問を持っています。以上、まとまりのない疑問ですが、なんとなく私がわからない部分はわかっていただいたのではないかと思います。この辺の話について、よろしくお願いします。

なんか基本的なことなんですけど、ちゃんと把握していないなーと思って質問します。

staticメソッドを使用してしまうと、メモリ上に残ってしまうからあまり使うななどとよく言うと思います。これに対して、staticでないメソッドは使用されている間はstaticと同じように管理され、使用後に開放対象となるということなのか。というか、非staticメソッドは、2箇所から同時にアクセスされたらメソッド2つ分のメモリを使用するのか。その前に、staticメソッドであっても、同時に2箇所からアクセスされたら2つ分のメ...続きを読む

Aベストアンサー

私がわかっている範囲内ですが、ざっとJava仮想マシン内のメモリ状況について整理してみます。

まずオブジェクトを保管するためのメモリ領域ですが、これは「メソッドエリア」と「ヒープ」の2つがあります。メソッドエリアはクラスを保管する場所であり、ヒープはインスタンスを保管する場所です。これとは別に、実行のためのエリアとして「Javaスタック」と呼ばれる領域がスレッドごとに用意されます。これが基本です。

Javaでプログラムが実行される(すなわち、新たなスレッドがたてられる)と、JVMは、まずそのスレッドが使用するためのJavaスタックをメモリ内に確保します。そして、メソッド等がコールされる度に「フレーム」と呼ばれる領域を作成し、そこに必要な情報を保管します。
 実行するスレッド内からオブジェクトが利用されようとすると、JVMはまず使用するクラスを「メソッドエリア」にロードします。そしてインスタンスを作成する際には、メソッドエリアにロードされたクラスをヒープにコピーし、インスタンスを作成します。
 プログラムからメソッドなどを利用する場合には、Javaスタック内にそのメソッド用のフレームを確保し、そこにローカル変数の情報やオペランドスタックなどを保管します。

従って、JVMの中では「クラス=メソッドエリア」「インスタンス=ヒープ」「利用するメソッド内で使用する変数類=実行するスレッドに対応するJavaスタック内のメソッドに対応するフレーム」という形でそれぞれ保管がされています。以上が、だいたいの概略です。


>staticメソッドを使用してしまうと、メモリ上に残ってしまうからあまり使うななどとよく言うと思います。

これは、要するに「staticなメソッドやフィールドはガーベージコレクタの対象とならない」ということがいいたいのでしょう。staticでないものは使用後にgcによってメモリから破棄されますから随時メモリはクリアされます。
 が、反面、staticでないものはnewによりインスタンスを作成する必要があり、これは実はけっこうなCPUへの負荷になります。従って、ごくわずかばかりのメモリ消費を気にするために不必要にstaticでないものを増やすと逆にCPUへの負荷を余計にかけてしまうことになるため、あまりよいとは思えません。
 また、そもそもstaticなものはインスタンスを作りませんから、でっかいインスタンスを作って不要になったら消すより、最初から作らないstaticの方がメモリに優しいでしょう。

>これに対して、staticでないメソッドは使用されている間はstaticと同じように管理され、使用後に開放対象となるということなのか。

Javaは、メソッド単位でロードをしていません。クラス単位です。まず、その点を勘違いしないようにしてください。で、おっしゃるようにstaticでないものは不要になった時点で(適当な時期に)ガーベージコレクタによりインスタンスが消去され、メソッドもメモリから消えます。

>その前に、staticメソッドであっても、同時に2箇所からアクセスされたら2つ分のメモリを消費するはずではないのか。

いいえ。staticなメソッドはクラス内に残るため、常に同一のものが参照されます。

>複数のアクセスがあったときに同時に処理ができるが、これは実質メモリ上に複数のメソッドが存在することにならないのか…

ローカル変数の内容については各スレッドのフレーム内に保持されますからアクセスが増えればメモリを消費しますが、staticなメソッドを利用する場合には各フレームにはstaticなメソッドへの参照だけがスタックされるだけで複数のstaticメソッドが積み上げられることはありません。
 非staticなメソッドは、newされただけインスタンスがヒープに作成されるため、同じメソッドが複数存在することはあります。

>ロードの際にはクラス単位で読み込まれるのか、メソッド単位なのか。staticメソッドと非staticメソッドが混在しているクラスでは、読込み、開放はメソッド単位で行っているのか。

クラス単位です。
staticと非staticが混在している場合、まずクラスがメソッドエリアにロードされた後、newした段階でヒープにインスタンスが作成されます。このとき、staticなものはクラス内に残されます。
 インスタンスは使用後に必要に応じてgcによって破棄されます。クラスは、スレッドが終了するまで保持されます。従って、staticメソッドはクラス内に保持されるため、同様にスレッドが終了するまでメモリ内に置かれます。


なお、私もまだまだ勉強不足なところがありますので、おかしな点がありましたらどなたか補足修正して下さい。

私がわかっている範囲内ですが、ざっとJava仮想マシン内のメモリ状況について整理してみます。

まずオブジェクトを保管するためのメモリ領域ですが、これは「メソッドエリア」と「ヒープ」の2つがあります。メソッドエリアはクラスを保管する場所であり、ヒープはインスタンスを保管する場所です。これとは別に、実行のためのエリアとして「Javaスタック」と呼ばれる領域がスレッドごとに用意されます。これが基本です。

Javaでプログラムが実行される(すなわち、新たなスレッドがたてられる)と、JVMは、...続きを読む

Qprivate static という変数の修飾

お世話になります。

private static final String HOGE = "hoge";

という変数(finalなので定数ですが)があるとします。このような、privateでstaticな変数というのは、どのような使われ方を意図しているのでしょうか?privateな変数がstaticである必要は、どのようなときに生じるのでしょうか?

よろしくご教授ください。

Aベストアンサー

 その private な変数が所属するクラス自身がいくつも定義された場合に、プログラム全体で1つのメモリしか確保されなくなります。
 なんで、メモリ量がものすげー切羽詰ってるときとか、ほんの数バイトでも節約した方がいい気がするときに有効です。

Q同じ配列またはクラスを、2回以上newしたとき

ファイルサイズ不定(ただし最大は10KB)のファイルを複数個読み込む際、ファイル個数分の配列を用意し生成するとメモリ不足になりかねないので、
読み込んだデータを使い終わったらすぐに破棄して別のデータを生成するといったような、1つの配列を使い回す方法を考えています。
(読み込んだbyte型の配列データは即座に4byte区切りでint型配列に変換し格納しています)

C++なら
 int *p;
 p = new int[1024*10];
 delete p;
 p = new int[1024*10];
 delete p;

みたいな方法で明示的に解放ができますが、
Javaではガーベッジコレクションで自動回収されるので
任意のタイミングで解放できないので、

int p[] = new int[1024*10];
p = null;
p = new int[1024*10];
p = null;

みたいな方法で試しているのですが、
こういった方法はやっぱりマズいのでしょうか?
JAVAヒープの容量を見る限りでは特に変化は見られず、素人の私では判断できないので、もしもご存知の方がいらっしゃればアドバイスいただけると助かります。
よろしくお願いします

ファイルサイズ不定(ただし最大は10KB)のファイルを複数個読み込む際、ファイル個数分の配列を用意し生成するとメモリ不足になりかねないので、
読み込んだデータを使い終わったらすぐに破棄して別のデータを生成するといったような、1つの配列を使い回す方法を考えています。
(読み込んだbyte型の配列データは即座に4byte区切りでint型配列に変換し格納しています)

C++なら
 int *p;
 p = new int[1024*10];
 delete p;
 p = new int[1024*10];
 delete p;

みたいな方法で明示的に解放が...続きを読む

Aベストアンサー

基本的にはその考え方でいいと思います。
ちなみにあえていちいちnullを代入しなくても、次のnewした配列を代入すれば
前の配列は参照されなくなるので、ガーベジコレクションの対象になります。

ただ、不要になったらガーベジコレクションで自動的に解放してくれると言っても、
短時間で急速に大量のインスタンスを生成すると、解放処理が追いつかなかったり、
追いついても解放処理のせいでパフォーマンスが低下する可能性があります。
質問の例のように配列を生成しては破棄するの繰り返しをやると、そうなる可能性があります。

配列の個数が1024*10と決まっているのであれば、newするのは最初だけにして、
2回目移行は内容の書き換えで対応した方が、ヒープの使用効率という点では現実的でしょう。
配列の個数が決まっていなくても、最大の個数がわかるのなら、やはりそのようにすべきでしょう。

あと思ったのは、どうしても同時に10*1024のintが必要なのかな?ということでした。
intひとつずつ処理するようなやり方できないのかなーと。

Javaはガーベジコレクションがあるからメモリ確保し放題というわけではもちろんなく、
生成しなくて済むインスタンスはできるだけ生成しない方が望ましいですし、
メモリリークのような現象もあります。
(すでに不要なインスタンスを気づかずライフサイクルが長い場所で参照しちゃってて解放されない、みたいな)

基本的にはその考え方でいいと思います。
ちなみにあえていちいちnullを代入しなくても、次のnewした配列を代入すれば
前の配列は参照されなくなるので、ガーベジコレクションの対象になります。

ただ、不要になったらガーベジコレクションで自動的に解放してくれると言っても、
短時間で急速に大量のインスタンスを生成すると、解放処理が追いつかなかったり、
追いついても解放処理のせいでパフォーマンスが低下する可能性があります。
質問の例のように配列を生成しては破棄するの繰り返しをやると、そ...続きを読む

QJavaでCSVファイルを高速に読む方法

最近、とある任務があって「数百万レコード」のCSVファイルを読み、
統計解析を実施するAPを自作したいと考えています。

しかし、ファイルのレコード数が膨大なため、解析する前にファイル読み込みに
大きな時間がかかってしまい困っています。

読み込みを高速化するために、複数のスレッドを用意し、スレッド毎に読みこむ
レコードの行を決めて、並列処理を行いたいと考えたのですが・・・

・任意の行をランダムに読むためRandomAccessFileクラスの利用を
 考えたがレコードが固定長でないと利用できない。

という点があり断念しています。私も詳しくはわかっていないのですがHadoopという
技術を使ってファイルを分割して並列処理するといった方法が取られているようですが
ファイルを高速に読み込む方法について、この質問を見ていただけた方の中で
こうすれば高速化できるというノウハウがもしあればご教授いただけるとありがたいです。

またできれば、複数の筐体にファイルを分割して分散処理するという大掛かりの手法ではなく、
一つの筐体で並列処理して高速化したいと考えています。

Javaは、あまり詳しくなくとんちんかんな質問かもしれませんがどうぞよろしくお願いします。

最近、とある任務があって「数百万レコード」のCSVファイルを読み、
統計解析を実施するAPを自作したいと考えています。

しかし、ファイルのレコード数が膨大なため、解析する前にファイル読み込みに
大きな時間がかかってしまい困っています。

読み込みを高速化するために、複数のスレッドを用意し、スレッド毎に読みこむ
レコードの行を決めて、並列処理を行いたいと考えたのですが・・・

・任意の行をランダムに読むためRandomAccessFileクラスの利用を
 考えたがレコードが固定長でないと利用できない。

...続きを読む

Aベストアンサー

Hadoopは大規模分散ファイルシステムであって、ファイルを分割して並列処理するというのとは違うみたいですが・・・

とりあえず私の思いついたのは読み込み専用スレッドを1つ用意しておいて順次解析用のスレッドを起動する方法かなぁ

Qinterface,extend,implementのちがい

お世話になります、

Javaを勉強しているのですが、
interface,extend,implementの使い分けがわかりません。

私の解釈としては、
(1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。

(2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。

(3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか?

とにかくこの3つのを使い分けるコツとかあれば教えてください。
よろしくお願いします。

Aベストアンサー

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば、getStringLength()メソッドなどが
あったほうが良いでしょうか。
このgetStringLength()メソッドは、2バイト文字も1バイト文字も「1文字」
と数えてくれると言う点で、まさに、日本語クラス用のメソッドだと言えるでしょう。

例えば、Java的に記述すると、、、
class Japanese {
public int getStringLength() {
  ・・・
return strlength;
 }
 ・・・
}

class TextField {
・・・
}

class JTextField extends TextField, extends Japanese {
・・・・
}

C++ではそのように実装するでしょう。
しかし、Javaにはこのような高度な機能はありません。

そこで、生まれた苦肉の策が、「interfaceとimplements」です。

interface Japanese {
public int getStringLength(); // interfaceは実装を含まない!
                 // すなわち「実装の継承」ができるわけではない。
}

class TextField {
・・・
}

class JTextField extends TextField implements Japanese {
・・・・
public int getStringLength() {
  ・・・
return strlength; //implementsの実装を「各クラスで」実装してやる必要がある。
 }
}


結局のところ、Javaでは、複数のクラスを親クラスには持ち得ないため、継承できなかったクラスは「各クラスで実装してやる必要性」があるのです。


ではどのように使うのが効果的か?

なまえのままです。「代表的なインターフェイス」にたいしてinterfaceを使うのが良いと思います。

例えば、プレイヤー系であれば、ビデオ・コンポ・ウォークマン・などにかかわらず、
interface controlpanel {
public play();
public stop();
public next();
public back();
}
というような基本的インターフェイスを「持っているべき」です。

こうすることで、それぞれのクラス宣言の際に、これらの「インターフェイスを持っているべきであり、実装されるべきである」ということを「強く暗示」することができます。
class videoplayer extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

こうすることで、同様のクラスを作成するユーザーは、
「プレイヤー系は、4つ操作が出来るコントロールパネルをインターフェイスとして持つべきなのだな!?」という暗示を受け取り、自分のクラスでもそれを模倣するでしょう。

class mp3player extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

また、これらのクラスを使用するユーザーも、「implements controlpanel」という
表記を見て、「4つの基本操作は押さえられているのだな!」という基本中の基本動作を抑えることが出来ます。

まとめると、クラスに「こういう特徴もたしてください!」「こういう特徴持ってますよ!」という一種の暗示的警告や方向性を与えることができるわけですね。

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば...続きを読む

QJavaで改行などが出来ないのです。

 Java の事で質問です。 
 

 System.out.println("このようにしても\n");

 改行できません。
 
 このようにしても\n   

 と表示されてしまいます。どうしてでしょう。ちなみにOSはMacOS9.1です。なにか関係があるのでしょうか?

Aベストアンサー

> class amigo{
> public static void main(String args[]) {
> System.out.print("aaaaaaaa");
> System.getProperty("line.separator");
> System.out.print("bbbbbbbb");
> }
> }
> のような使い方でしょうか?

String line_sep = System.getProperty("line.separator");
System.out.println("あいうえお" + line_sep + "かきくけこ");

こうです。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報