Javaでリストとかfor文とか
Pythonでは「複数のオブジェクトが入った配列のようなオブジェクト」を下のような記法で作成できます。
>>> xs = [1, 2, 3.14, "Hello!"]JavaScriptやRubyでも同じで、Perlだと@xs = (1, 2, 3.14, "Hello")になるようです。
また、このオブジェクトの中身を順に表示するにはfor文を使います。
>>> for x in xs: print x 1 2 3.14 Hello!
これと同じことをJavaではどう書けばいいのか、 今日やっと理解しました。 Javaでは下のようになります。
Object[] xs = { 1, 2, 3.14, "Hello!" }; for (Object x : xs) { System.out.println(x); }ただ、これではxsが配列なので、 Pythonでは下のように書ける「アイテムの追加」などができません。
>>> xs = [1, 2, 3.14, "Hello!"] >>> xs.append("Java") >>> xs [1, 2, 3.1400000000000001, 'Hello!', 'Java']アイテムの追加などが可能なオブジェクトにするために、 Collectionインターフェイスを実装したクラス (Collection (Java 2 Platform SE 5.0)) のオブジェクトを作りたいと思います。 それにはArrays.asListを使います。
Vector<Object> xs = new Vector<Object>(Arrays.<Object>asList(1, 2, 3.14, "Hello!"));Arrays.asListに配列を渡すと、List(これはCollectionの子インターフェイス)を 実装したクラス(Arrays$ArrayList)のオブジェクトを返してくれます。 なので下のように配列を渡しても上と同じことができます。
Arrays.asList(new Object[]{ 1, 2, 3.14, "Hello!"})可変長引数でも渡せるので、実際に配列を作る必要はなく、 配列を作るための呪文「new Object[]{~}」が省けます。 ただしその場合「これらがObject型である」という情報が失われてしまうので、 それを補うために「Arrays.<Object>asList」と指定しています。
さて、これでListを作るところまではできたのですが、 残念ながらここで作られるListのaddメソッドを呼ぶと、 「サポートされていない」という趣旨の例外が発生します。 (UnsupportedOperationException)
おそらく、配列をListに詰め替えているのではなく、 単にListに見えるラッパをかぶせているだけなのでしょう。 そこでVectorに詰め替えます。 VectorのコンストラクタにCollectionを渡した場合には、 中身の詰め替えが行われます。 正確に言うならば、仕様にはそういうことは書かれていない (どころか、返ってくるリストがArraysのprivateなインナークラスなのでそもそも以下略) のでソースコードを追うことになります。 Vectorのコンストラクタで、渡されたCollectionのtoArrayを呼ぶのですが、 Arrays$ArrayListのtoArrayは自分の持っている配列をcloneして返すので、 この時点で詰め替えが行われます。
さてこれで追加や削除ができるようになりました。 ここでクイズです。下のコードを実行するとどういう出力が出るでしょうか?
Vector<Object> xs = new Vector<Object>(Arrays.<Object>asList(1, 2, 3.14, "Hello!")); xs.remove(3.14); xs.remove(1); xs.set(1, "newItem"); xs.add(1, 999); xs.add("Java"); Collections.reverse(xs); for (Object x : xs) { System.out.println(x); }
ヒント、Pythonで書くとこうなります。
>>> xs = [1, 2, 3.14, "Hello!"] >>> xs.remove(3.14) >>> xs.pop(1) 2 >>> xs[1] = "newItem" >>> xs.insert(1, 999) >>> xs.append("Java") >>> xs.reverse() >>> for x in xs: print x
解答。
Java newItem 999 1出力結果に「1」が入っているのが意外です。 実はxs.remove(3.14);とxs.remove(1);ではremoveの意味が違い、 前者は「3.14という値を取り除く」のに対し、後者は「1番目の位置の値を取り除く」 になっています。 いやはや、Javaは奥が深いですね。
追記: なぜこういう現象が起きるのかについて解説します。remove(int)とremove(Object)の両方のメソッドがあって、リテラルの1は(過去の諸々のしがらみによって)int型なのでremove(1)はremove(int)が呼ばます。一方リテラルの3.14はオートボクシングでObjectになるのでremove(Object)の側が呼ばれます。もしremove(Object)で1を削除したければ 明示的にxs.remove(new Integer(1));と書く必要があります。
ご指摘どうもありがとうございます>Yのほぼコード置場 - Re:Javaでリストとか(ry