2011-02-09 9 views
1

私はこのコードでは意味:for-eachループで整数を増やすことができないのはなぜですか?

List<Integer> list = new LinkedList(); 
list.add(1); 
list.add(2); 
list.add(3); 

for (Integer i : list) 
    i++; 

System.out.println(list.get(0)) 

リターン1ない2. Javaは新しいオブジェクト(i)とのコピーを作成するために、各ループでは、リスト内のオブジェクトから値をフィールド?

+0

質問は良い冗談になります:) – bestsss

答えて

8

Integer Sは不変です。

コードでは、i変数が、より新しい値を持つ新しいIntegerインスタンスを指すように変更されています。

元のIntegerインスタンスはリストにありません(変更できません)。

+0

「整数」オブジェクトが不変であることを忘れていました。何が残念なのですか? – rll

+1

@rll:実際には、非常に良いことですが、 'Integer'オブジェクトは不変です! – ColinD

+0

ちょうどニックピック、 '大きな値を持つインスタンス'は、それほど小さいものでもありえます:) – bestsss

0

リスト中の0番目の要素は、あなたが行に2

を追加した「1」、ああ、私は理解しているので:あなたは、整数をインクリメントします。あなたはする必要があります:

for(int i=0; i<list.size(); i++) { 
    list.set(i,list.get(i)+1); 
} 

整数インスタンスが不変であることに注意してください。値は変更できません!

+1

は今度はリストイテレータを使用する必要がありますO(n * n) – bestsss

+0

あなたは正しいです。私はLinkedListに注意しなかった、それがArrayListだと思った。 – Daniel

9

++演算子はIntegerオブジェクトの有効な演算子ではないため、Javaは自動ボクシング機能を使用してIntegerオブジェクトをintプリミティブに変換します。それが変換されると、intプリミティブがインクリメントされます。あなたはプリミティブを保存しないので、それは失われます。

あなたは

List<Integer> list = new LinkedList(); 
list.add(1); 
list.add(2); 
list.add(3); 


for (int index; index < list.size(); index++) { 
    int value = list.get(index).intValue(); 
    value++; 
    list.set(index, Integer.valueOf(value)); 
} 

System.out.println(list.get(0)) 

上記のコードのような何かをする必要がある目標を達成するためには最適ではありません。 autoboxingは使用しません。このループは重くオートボクシング使用していますあなたは何をオートボクシングのアイデアを取得したい場合は、カバーの下にやっていること^)

ListIterator<Integer> iterator = list.iterator(); 
while (iterator.hasNext()) { 
    iterator.set(iterator.get()++); 
} 

注意、同等のソリューション:最適化されたソリューションは、(好評につき追加)反復子を使用します以下に示すオートバイには依存しません。

ListIterator<Integer> iterator = list.iterator(); 
while (iterator.hasNext()) { 
    iterator.set(Integer.valueOf(iterator.get().intValue()++)); 
} 
+0

+1また、 'Integer'は不変です。なぜなら、オートボックス –

+2

' ++ '**は** Integer上の有効な演算子であり、変数は前のものより1つ高い' Integer'を参照するように変更します。これがうまくいかない本当の理由は、 'Integer'は不変であり、' ++ 'は新しいバージョンしか作成しないということです。 –

+0

いいえ、タイプが整数の「オブジェクトi」は決して増加しません。もしそうであれば、 "Object i"と呼ばれるメソッドがあり、 "++"はメソッドではありません。 「オブジェクトi」はオートボクシングのために「プリミティブi」に変換され、「プリミティブi」はインクリメントされます。これにより、「オブジェクトi」はそのままになります。 –

7

それは許していると思いますが、それはできません。

あなたが持っているものは略語です。

for (Iterator<Integer> iter = list.iterator(); iter.hashNext();) { 
    Integer i = iter.next(); 
    i++; // value is discarded after this line. 
} 

EDIT:かなりのget(i)とLinkedListのために非常に高価になることができますセット(I、値)を使用するよりも、より良い選択は、反復子を使用することです。整数の

for (ListIterator<Integer> iter = list.listIterator(); iter.hasNext();) 
    iter.set(iter.next()+1); 
+2

+1イテレータを使用するのが実際には最適な解決方法です。 – ColinD

+0

それ以外の場合、LinkedListは、n番目の要素を検索して設定するたびに、リストを先頭から逆順に変換する必要があります。 –

+1

最適な最適化。私はリストイテレータが好きです。 –

0

IntegerはちょうどStringように、不変であるため、など

オペレータ++だけでやってようなものです:

i = new Integer(i.intValue()+1);` 

あなたは値を変更するlist.set(index, i);する必要がありますあなたのリストに。

for (int index=0; index<list.size(); index++) { 
    list.set(index, list.get(index)+1); 
} 
+0

そして、ループのような 'set()'を呼び出すべきではありません。コレクションをループし、そのループでコレクションを変更する必要がある場合は、明示的な 'Iterator'を使用する必要があります。 –

+1

'new Integer()'を使うのは、自動ボックス化を使うよりも高価です。なぜなら、後でIntegerのキャッシュを使用し、書き込み/読み出し時間が長くなるからです。 –

+0

@Peter、実際には 'Integer.valueOf(int)'は、それは、JVMがコードを最適化できないようにします。割り当てが行われるかどうかはわかりません(-128 - +127は非常に制限されています)。その特定のケースでは、割り当ては「エスケープ」されますが、他のものではそうではなく、新しいInteger()はちょうど良い(またはそれ以上)でしょう。 – bestsss

0

すべての答えがここにそれが可変タイプでどのように見えるか、不変性についてであるため、この出力すべき2

import java.util.concurrent.AtomicInteger; 


List<AtomicInteger> list = new LinkedList<AtomicInteger>(); 
list.add(new AtomicInteger(1)); 
list.add(new AtomicInteger(2)); 
list.add(new AtomicInteger(3)); 

for (AtomicInteger i : list) 
    i.getAndIncrement(); 

System.out.println(list.get(0)); 

。 (のAtomicIntegerは、さらにこれらのスレッドの安全性を有しているが、我々はここでの唯一の可変性を必要とする。)

以下のバリアントが出力1まだだろうように、(すべてのプリミティブなど)プリミティブ型intは、あまりにも、不変である:

int[] list = new int[]{ 1, 2, 3}; 

for (int i : list) 
    i++; 

System.out.println(list[0]); 
関連する問題