2013-05-11 62 views
2

的我與這些私有成員的類:對象消失的ArrayList

private ArrayList<ArrayList<ArrayList<CustomStuff>>> listOfPaths; 
private int currentIndex; 

我填的是陣列的方法是這樣的:

listOfPaths.get(currentIndex).add(path); //path is ArrayList<CustomStuff> 

一切都很好至今。
檢查:

System.out.println(listOfPaths.get(currentIdx).get(listOfPaths.get(currentIdx).size() - 1).size()); 

給出正確的尺寸。

現在:方法結束後。 ArrayList<ArrayList<ArrayList<CustomStuff>>>

因此System.out.println(listOfPaths.get(anyValidIdx).get(anyValidIdx).size());將始終爲1!

順便說一句:listOfPaths.size()listOfPaths.get(anyValidIdx).size()給出正確的尺寸!

所以只有數組的第三維似乎縮小到一個單一的對象。

什麼問題?

背景故事: 我有矩陣上的點。開始和結束標記。在這些標記之間,我有路徑。路徑由步驟組成。 so:
- 路徑爲ArrayList<Step>
- 對於相同的開始/結束標記的不同路徑的集合是:ArrayList<ArrayList<Step>>
- 矩陣上的所有集合都是ArrayList<ArrayList<ArrayList<Step>>>

我從一對標記開始,尋找所有可用的路徑。當我搜索添加的每個找到的路徑:listPaths.get(currentIndex).add(pathBetweenStartAndEnd)
所以,當我完成讀取路徑,一對標記,我遞增CURRENTINDEX並移動到下一對標記等等...

完整代碼:

import java.util.ArrayList; 

public class Solver { 

    protected GameBoard board; 

    private static ArrayList<ArrayList<ArrayList<BoardCell>>> listOfPaths; 
    private int currentPair; 

    public GameBoard getSolvedBoard() { 
     solve(); 
     return board; 
    } 

    public void setBoard(GameBoard board) { 
     this.board = board; 
    } 

    public Solver(GameBoard board) 
    { 
     super(); 

     this.board = board; 
    } 


    protected void solve() 
    { 
     listOfPaths = new ArrayList<ArrayList<ArrayList<BoardCell>>>(); 
     currentPair = 0; 

     for(CellPair pair : board.getPairs()) 
     { 
      System.out.printf("Getting paths for %d:\n", pair.getFirstCell().getValue()); 

      ArrayList<BoardCell> path = new ArrayList<BoardCell>(); 
      path.add(pair.getFirstCell()); 

      listOfPaths.add(new ArrayList<ArrayList<BoardCell>>()); 

      DFS(pair.getFirstCell(), pair.getSecondCell(), new ArrayList<BoardCell>(), path); 

      System.out.println("--------------------------------------------------"); 

      ++currentPair; 
     } 

     System.out.println(listOfPaths.get(0).get(0).size()); 
     //System.out.println(listOfPaths.get(2).get(205).get(1)); 
    } 

    protected static ArrayList<BoardCell> getSonsForCellOnBoard(BoardCell cell, GameBoard board) 
    { 
     int row  = cell.getRow(), 
      column = cell.getColumn(); 

     ArrayList<BoardCell> neighbors = new ArrayList<BoardCell>(); 

     if(row > 0) 
      neighbors.add(board.getCellAtIndex(row - 1, column)); 
     if(row < board.getNumberOfRows() - 1) 
      neighbors.add(board.getCellAtIndex(row + 1, column)); 
     if(column > 0) 
      neighbors.add(board.getCellAtIndex(row, column - 1)); 
     if(column < board.getNumberOfColumns() - 1) 
      neighbors.add(board.getCellAtIndex(row, column + 1)); 

     return neighbors; 
    } 

    private void DFS( BoardCell source, 
         BoardCell target, 
         ArrayList<BoardCell> visited, 
         ArrayList<BoardCell> path ) 
    { 
     if(source.getRow() == target.getRow() && source.getColumn() == target.getColumn()) 
     { 
      System.out.printf("PATH: %d: ", path.size()); 
      System.out.println(path); 

      ArrayList<BoardCell> temp = new ArrayList<BoardCell>(); 
      temp = path; 

      listOfPaths.get(currentPair).add(temp); 

      System.out.println(listOfPaths.get(currentPair).get(listOfPaths.get(currentPair).size() - 1).size()); 

      return; 
     } 

     for(BoardCell son : Solver.getSonsForCellOnBoard(source, board)) 
     { 
      if(visited.contains(son)) 
       continue; 

      if(son != target && 
        son.getType() == BoardCell.BoardCellType.BoardCell_AnchorCell) 
       continue; 

      path.add(son); 
      visited.add(son); 

      DFS(son, target, visited, path); 

      visited.remove(son); 
      path.remove(path.size() - 1); 
     } 
    } 
} 
+0

爲什麼你有ArrayList的'ArrayList'的'ArrayList'?必須有一個更好的數據結構。 – 2013-05-11 19:19:48

+1

'ArrayList >>'如果你看到這樣的代碼,你真的需要重新考慮你的結構......那麼多嵌套泛型不會幫助調試 – Doorknob 2013-05-11 19:19:51

+0

正如我所說的。我是新來的Java。如果你知道更好的收藏,請讓我知道。事情是,這不一定是通用的。它總是必須保持3個暗淡。無論如何,我仍然有興趣知道我的情況出了什麼問題。 – 2013-05-11 19:22:15

回答

4

在Java非基元類型(存儲在路徑中的情況下的列表)是通過引用而不是按值傳遞的。

當你撥打:

DFS(son, target, visited, path); 

最終在遞歸結束時,您存儲在您listOfPaths路徑。

但之後你做的:

visited.remove(son); 
path.remove(path.size() - 1); 

由於道路被作爲引用傳遞的任何變化會影響到一個存儲在您的listOfPaths。

所以更換本(溫度是多餘的在這種情況下BTW):

ArrayList<BoardCell> temp = new ArrayList<BoardCell>(); 
temp = path; 

listOfPaths.get(currentPair).add(temp); 

有了這個(僅僅複製路徑列表):

ArrayList<BoardCell> temp = new ArrayList<BoardCell>(); 
for (BoardCell bc : path) 
    temp.add(bc); 

listOfPaths.get(currentPair).add(temp); 

,並查找代碼中的更多地方使用這個類似的問題。

+0

輝煌。有用。非常感謝你!幫助我學習Java! – 2013-05-11 20:12:42

+0

這不是100%正確的。 [對象不是通過引用傳遞,雖然它看起來像他們](引擎蓋下他們是指針和Java中的大多數(http://stackoverflow.com/questions/40480/is-java-pass-by-reference) – nkr 2013-05-11 20:14:29

+0

@nkr你學會使用它們作爲參考(當然取決於你如何解釋單詞引用),因爲你不能在Java中做*指針。你可能來自C++世界:),如其中一條評論 – giorashc 2013-05-11 20:18:55