2017-07-19 64 views
1

我想將一個整數數組添加到ArrayList。在某些條件下元素充滿有效信息;否則數組填充-1。通過引用調用錯誤地修改數組元素

List<int []> starArray = new ArrayList<>(); 
    int [] star = {-1, -1, -1}; 
    for (int i = 0; i < 10; i++) { 
     if (i < 5) { 
      star[0] = i; 
      star[1] = 2*i; 
      star[2] = 3*i; 
      starArray.add(star); 
     } else { 
      star[0] = star[1] = star[2] = -1; 
      starArray.add(star); 
     } 
    } 

問題是,一旦它進入else並設置star = 0,都在starArray的元素將設置爲-1。這意味着,在循環之後,我得到了starArray中的全部-1。我想要這個結果

0#0#0 
1#2#3 
2#4#6 
... 
-1#-1#-1 

看起來參考被添加到starArray。我想解釋的是我想創建一個具有3個元素的臨時數組(星號)。所以明星將佔用96個字節。然後我將這96個字節移動到一個ArrayList。接下來,我在Star的同一位置創建另外3個元素數據,並將另外96個字節推送到ArrayList。因此,通過推2 star到ArrayList中,我將使用

96 bytes => original star 
96 bytes => first element of ArrayList 
96 bytes => second element of ArrayList 

所以,我怎樣才能解決呢?

+1

通過創建數組的副本。 – Kayaman

+0

@chris:我不想那樣!因爲starArray [0]實際上是{0,0,0}和... – mahmood

+0

@Kayaman:我想創建一個單個數組並對其進行多次修改。否則,我必須在循環內創建數組,並且對於大循環,它浪費了內存位置。 – mahmood

回答

4

您要添加多個引用到相同數組列表中,這樣一個變化將不可避免地改變其他人。你需要在每次迭代創建一個新的數組:

... 
for (int i = 0; i < 10; i++) { 
    int[] star = {-1, -1, -1}; // create a new array each iteration 
... 

在當前版本中,畫面看起來是這樣的:

 
star   [...] 
      /| \ 
      +---+---+---+ 
starArray | | | | 
      +---+---+---+ 

請注意,所有引用實際上指向一個單一內存中的數組。現在,我們正在這樣做:

 
star [...] [...] [...] 
      \ | /
      +---+---+---+ 
starArray | | | | 
      +---+---+---+ 

即我們正在創建多個可以獨立修改的物理數組。對不起,這是壞的ASCII藝術。


如果你真的關心的內存使用情況,一種方法,你可以嘗試將其用於{-1, -1, -1}個單一的陣列,只要你會不會在未來的變異這些陣列:

int[] starNegOne = {-1, -1, -1}; 
for (int i = 0; i < 10; i++) { 
    if (i < 5) { 
     int[] star = {i, 2*i, 3*i}; 
     starArray.add(star); 
    } else { 
     starArray.add(starNegOne); 
    } 
} 

無論何時添加{-1, -1, -1}陣列,都可以節省空間。

+0

請參閱我的評論。假設一個由3個整數組成的數組被創建並被推送到ArrayList。它會在內存中存儲6個位置嗎? – mahmood

+0

@mahmood「內存中的位置」不一定是一個有意義的度量,但通常每個length-3 int數組佔用一些不變的空間(12個字節+通常的數組/對象開銷),所以創建更多的數組這裏自然會使用更多的空間。 – arshajii

+0

@mahmood看我的編輯。 – arshajii

4

是的你是對的。不要在for之外創建數組。在裏面創建並將其添加到列表中。否則它會多次修改相同的對象,並多次添加到列表中,並最終具有相同的值。

for (int i = 0; i < 10; i++) { 
    int [] star = {-1, -1, -1}; 
     if (i < 5) { 
      star[0] = i; 
      star[1] = 2*i; 
      star[2] = 3*i; 
     } 
     starArray.add(star); 
    } 

而且當您重複相同的代碼時,還可以完全刪除else。


不,如果你看一下你的預期輸出

0#0#0 
1#2#3 
2#4#6 
... 
-1#-1#-1 

所有陣列具有不同的值,你還期待一個陣列應該保持這個?沒有恕我直言。

+0

請注意,'else'內的賦值不再是必需的。 – shmosel

+1

@shmosel其他部分本身不需要。剛剛刪除它。 –

+0

也許這個片段你是對的。但實際問題不是這樣。因爲我沒有寫出原始代碼。我試圖展示一個場景來顯示問題 – mahmood

3

插入一個新的匿名數組中的每個循環迭代

List<int[]> starArray = new ArrayList<>(); 
//int [] star = new int[]; 
for (int i = 0; i < 10; i++) { 
    if (i < 5) { 
     //star[0] = i; 
     //star[1] = 2*i; 
     //star[2] = 3*i; 
     starArray.add(new int[]{i, 2*i, 3*i}); 
    } else { 
     //star[0] = star[1] = star[2] = -1; 
     starArray.add(new int[]{-1, -1, -1}); 
    } 
} 
+0

這不會創建/新的無用內存位置嗎?我想創建一個數組並多次修改它。否則,我必須在循環內創建數組,並且對於大循環,它浪費了內存位置。 – mahmood

+0

將循環分成兩部分可能也是一個好主意,用'0.. <5'和'5 .. <10'。 – Clashsoft

+2

@mahmood他們用什麼方式無用?他們正在存儲您的數據。如果只添加一個數組,則只會有一個數組的數值。 – azurefrog