- - PR -
多次元配列(?)の長さを取得したい場合
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2003-03-13 14:46
ありがとうございます!
早速作ってみました。うまくいきました。 で、ついでにこれの応用で、プリミティブの型用の物もつくろうと、getCountの同一名称 で引数を int[] に変更してみたところNGでした。 array[i] instanceof int[] でコンパイル時にエラーが出てしまいました。 検出値 : int 期待値 : int[] プリミティブの型を実行時に判定するには無理があるので仕方がないかな? 一瞬、配列もオブジェクトじゃねーか?と思ったのだが、あきらめよう。 <ソース> class countArray{ public static int getCount(Object[] array) { int count = 0; for( int i = 0;i < array.length; i ++ ){ if( array[i] instanceof Object[] ){ count += getCount((Object[])array[i]); }else{ count = array.length; } } return count; } public static void main(String[] args){ String[] a = new String[10]; String[][] b = new String[20][30]; String[][][] c = new String[30][40][50]; String[] d1 = new String[60]; String[] d2 = new String[70]; String[] d3 = new String[80]; String[][] d = { d1, d2, d3 }; System.out.println("a:"+getCount(a)); System.out.println("b:"+getCount(b)); System.out.println("c:"+getCount(c)); System.out.println("d:"+getCount(d)); } } <結果> a:10 b:600 c:60000 d:210 [ メッセージ編集済み 編集者: maru 編集日時 2003-03-13 15:11 ] | ||||
|
投稿日時: 2003-03-13 15:26
こんにちは。返答ありがとうございます。 確かに、配列の配列の・・・(以下続く)は、配列の参照の配列の参照・・・(以下続く) なので、掛け算のコストに比べて遅いかもしれませんね。(どれほどかわかんないけど) 巨大な座標データなどを配列に落とし込む場合は、多次元配列に落とすより、1次元配列 に落としてアクセスしたほうがいいでしょうね。 ただ今回は、どちらかといえば配列を作る(newする)側ではなくて、配列を受け取って処理 する側のクラスを作っていて、(オブジェクト指向チックに)汎用的に使えるように考えて、 もらう配列の次元数に固定しない処理の方がいいかな?と思って、疑問に思ったのでした。 どちらも一長一短で場合によって使い分けですね。 [ メッセージ編集済み 編集者: maru 編集日時 2003-03-13 15:29 ] | ||||
|
投稿日時: 2003-03-13 15:40
unibon です。こんにちわ。
私も、引数に配列の配列を渡してもらうようなメソッドを作っている際に、 maruさんと同じ疑問を持ったことはあります。 で、そのときは a[0].length だけを見る(その他の a[1].length などは見ない)、 という仕様で逃げてしまいました。 この問題は、matrix 関連を扱うかたなら誰もが広く共通して持つ問題だと思うので、 なにかもっと良い解法のパターンがあってもよさそうな気がしますが、 私はいまだに見つけられません。 #JDK のソースコードなどを見たらよいのかな、と思っていますが。 | ||||
|
投稿日時: 2003-03-13 15:44
失礼しました、確かにint[]はinstanceof Object[]ではダメみたいですね。
そこで、ClassのisArrayで判断してreflectパッケージのArrayでアクセスするという方法をちょっと試してみました。
こんな具合になりました。 厄介なのは、Object[]が来ると要素が配列だったり配列じゃなかったりする、というところで、配列を見つけたらその分だけ減算させました。 役に立つかは解らないけど、これで当初の目的は達成できますかね? | ||||
|
投稿日時: 2003-03-13 15:47
R−55さんの書き込み(2003-03-13 15:26)より
あ(汗)、個別に処理できるのを忘れてました。 個人的には、メンバとしてクラスの中に隠蔽しちゃう癖があるので、 1次元配列×nで済ましちゃう事が多いですね。 #単純な配列を返してもらうよりは、java.util.Collection関連のオブジェクトを #投げてもらう方が、キレイかな・・・とは思ったり。 | ||||
|
投稿日時: 2003-03-13 16:25
こんにちは。みなさん、ありがとうございました。
jack_pmaさんの案も盛り込んで、以下のようなクラスができました。 本当は、getCountメソッドをオーバーロードで、共通名で作りたかったのですけど、 コンパイルはとおるのですが、なぜか結果が正しくありませんでした。 プリミティブ型の方のgetCountをコールすると、メソッドの中の再帰処理でクラス型の 方のgetCountを呼んでいるのかな? あいまいなコードがかけないはずのjavaであいまいな処理をさせてしまっているのかな? 当初は、この議題はそんなに深く考えていなかったのですけど、結構勉強になりました。 今回作ったクラスは実際に使うかは分からないけど(すいません)、今後の参考になると 思います。 <ソース> import java.lang.reflect.Array; class countArray{ /* クラス型配列 */ public static int getCount(Object[] array) { int count = 0; for( int i = 0;i < array.length; i ++ ){ if( array[i] instanceof Object[] ){ count += getCount((Object[])array[i]); }else{ count = array.length; } } return count; } /* プリミティブ型配列 */ public static int getCount2(Object ary){ if (!ary.getClass().isArray())return 0; int len = Array.getLength(ary); int cnt = len; for (int i=0; i<len; i++){ Object obj = Array.get(ary, i); if (obj != null){ if (obj.getClass().isArray()){ cnt--; cnt +=getCount2(obj); } } } return cnt; } public static void main(String[] args){ String[] a = new String[10]; String[][] b = new String[20][30]; String[][][] c = new String[30][40][50]; String[] d1 = new String[60]; String[] d2 = new String[70]; String[] d3 = new String[80]; String[][] d = { d1, d2, d3 }; int[] e = new int[100]; int[][] f = new int[20][30]; double[] g = new double[40]; float[][] h = { new float[40], new float[50], new float[60]}; System.out.println("a:"+getCount(a)); System.out.println("b:"+getCount(b)); System.out.println("c:"+getCount(c)); System.out.println("d:"+getCount(d)); System.out.println("e:"+getCount2(e)); System.out.println("f:"+getCount2(f)); System.out.println("g:"+getCount2(g)); System.out.println("h:"+getCount2(h)); } } <結果> a:10 b:600 c:60000 d:210 e:100 f:600 g:40 h:150 | ||||
