在Arraylists的ArrayList中,为什么所有对单个元素的操作都会影响所有其他索引?

问题描述:

我已经嵌套在撰写一本书的ArrayList:在Arraylists的ArrayList中,为什么所有对单个元素的操作都会影响所有其他索引?

private ArrayList<ArrayList<PageContents>> book = new ArrayList<>(); //A list of lists 
private ArrayList<PageContents> page = new ArrayList<>(); //A List of objects 

book.add(page); //Add new(first) page in book. 
PageContents pageContents = new PageContents(); //Create a new line 
pagecontents.setLine("This is a line on the page"); //Edit the line 
book.get(0).add(pagecontents); //Add the new (first) line to the first page of the book. 

因此,在实践中,book.get(0).get(0).getLine();将返回的书的第一页的第一行。

的问题

我最初以为一切工作正常,因为我开发的初始部分涉及得到一个单页的权利,那么我会担心多页。然后,当我将page列表附加到book ArrayList与book.new(page);我发现它与pagebook.get(0)完全一样。 因此,book.get(0).get(0)的值与book.get(1).get(0)完全相同,或者book.get(0).get(20)book.get(1).get(20)完全相同。

然后我想:“没什么大不了的,它必须复制book.get(0)的数据,我只是在创建完成后立即清除page阵列列表book.get(1).clear();。”但是,这也清除了book.get(0)。然后我改变了数据book.get(1).get(9);,并且它也将book.get(0).get(9);更改为相同的值。

现在我不知道发生了什么。我认为这可能与几行内容有关,我将“书籍”数据与不同的类同步,可能是在复制指针,以便每个“页面”指向相同的数据,但是在测试之后,我消除了作为罪魁祸首。 (我刚刚删除了这些方法)

我的ArrayLists是否在我的实现中有缺陷?
到目前为止,ArrayList结构对我来说是完美的(直到我需要一个新的page,就是这样)。我只需要每个新的page数组列表都是空白的,并将其添加到book列表中。

任何帮助表示赞赏。多谢你们!

更完整的示例:

代码

private ArrayList<ArrayList<PageContents>> book = new ArrayList<>(); //A list of lists 
private ArrayList<PageContents> page = new ArrayList<>(); //A List of objects 

book.add(page); //Add new(first) page in book. 
PageContents pageContents1 = new PageContents(); //Create a new line 
pagecontents1.setLine("This is Line 1 on Page 1"); //Edit the line 
book.get(0).add(pagecontents1); //Add the new (first) line to the first page of the book. 

System.out.println("Page1 size: " + book.get(0).size() + "pages"); 
System.out.println("Page1: " + book.get(0).get(0).getLine()); 

System.out.println("Page2 size: " + book.get(1).size() + "pages"); 

if(book.get(1).isEmpty()) //Should book.get(1) should be empty 
{ 
    System.out.println("Page2: EMPTY"); 
} 
else 
{ 
    System.out.println("Page2: " + book.get(1).get(0).getLine()); 
} 

输出(错误)

Page1 size: 1 
Page1: This is Line 1 on Page 1 
Page2 size: 1 
Page2: This is Line 1 on Page 1 

输出(它应该是什么,如果代码借机如预期d)

Page1 size: 1 
Page1: This is Line 1 on Page 1 
Page2 size: 0 
Page2: EMPTY 

如果我添加这些新代码(为了让第2项内容)

PageContents pageContents2 = new PageContents(); //Create a new line 
pagecontents2.setLine("This is Line 1 on Page 2"); //Edit the line 
book.get(0).add(pagecontents1); //Add the new (first) line to the second page of the book. 

System.out.println("Page1 size: " + book.get(0).size() + "pages"); 
System.out.println("Page1: " + book.get(0).get(1).getLine()); 
System.out.println("Page2 size: " + book.get(1).size() + "pages"); 
System.out.println("Page2: " + book.get(1).get(1).getLine()); 

输出(不正确的,这两个页面进行同样的更改)

Page1 size: 2 
Page1: This is Line 1 on Page 1 
Page2 size: 2 
Page2: This is Line 1 on Page 1 
Page1 size: 2 
Page1: This is Line 1 on Page 2 
Page2 size: 2 
Page2: This is Line 1 on Page 2 

由于我添加了一个新行,两个page列表都有2行。每个应只有一行不同的值。

+0

第一件事,你是等号需要在引文中:'=“pages”'应该是'+“= pages”'。或者将'='改成'+',这样你只需要'+'页面“' –

+0

是的,简单的复制/粘贴错误。我修好了它。意思是把一个'+'连接起来。 – LazyBear

+0

确保在开始创建第二页之前将'page'设置为新的ArrayList;否则你只需将同一页面添加到'book'两次,并在第二次迭代中修改它。 – Gus

import java.util.ArrayList; 

class PageContents 
{ 
    String Line; 

    public String getLine() 
    { 
     return Line; 
    } 

    public void setLine(String line) 
    { 
     Line = line; 
    } 

} 

public class MainClass 
{ 
    public static void main(String[] args) 
    { 
     ArrayList<ArrayList<PageContents>> book = new ArrayList<>(); 
     ArrayList<PageContents> page1 = new ArrayList<>(); 

     // Add new(first) page in book. 
     PageContents pageContents1 = new PageContents(); 
     pageContents1.setLine("This is Line 1 on Page 1"); 
     page1.add(pageContents1); 
     book.add(page1); 

     ArrayList<PageContents> page2 = new ArrayList<>(); 
     PageContents pageContents2 = new PageContents(); 
     pageContents2.setLine("This is Line 1 on Page 2"); 
     page2.add(pageContents2); 
     book.add(page2); 

     System.out.println("Page1 size: " + book.get(0).size() + "pages"); 
     System.out.println("Page1: " + book.get(0).get(0).getLine()); 

     System.out.println("Page2 size: " + book.get(1).size() + "pages"); 

     if (book.get(1).isEmpty()) 
     { 
      System.out.println("Page2: EMPTY"); 
     } else { 
      System.out.println("Page2: " + book.get(1).get(0).getLine()); 
     } 
    } 
} 
+0

这就是答案。正如少数人建议的那样,我需要创建一个新的“页面”列表,然后将其添加到“书籍”列表中。在Nani'2015的回答中,它是'ArrayList page2 = new ArrayList ();'我实际上认为我正在这样做,但是我试图解决这个问题的实际程序更具动态性,添加为页面1创建的第一个“页面”。在我的实际程序中,新的“页面”是在方法调用中创建的,所以我只是在那里创建了'newPage'列表并将其添加到'book'列表中。现在,每个添加到“book”的newPage都是一个新实例。感谢大家。 – LazyBear

你确定你的演示程序是正确的吗?

我试了下面的代码,并得到了一个ArrayIndexOutOfBounds异常。你的代码必须做的事情比你贴什么更多...

Exception in thread "main" Page1 size: 1pages 
Page1: This is Line 1 on Page 1 
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 
    at java.util.ArrayList.rangeCheck(Unknown Source) 
    at java.util.ArrayList.get(Unknown Source) 
    at BookThingy.main(BookThingy.java:17) 

代码...

import java.util.ArrayList; 

public class BookThingy { 

    public static void main(String[] args) { 
     ArrayList<ArrayList<PageContents>> book = new ArrayList<>(); //A list of lists 
     ArrayList<PageContents> page = new ArrayList<>(); //A List of objects 

     book.add(page); //Add new(first) page in book. 
     PageContents pageContents1 = new PageContents(); //Create a new line 
     pageContents1.setLine("This is Line 1 on Page 1"); //Edit the line 
     book.get(0).add(pageContents1); //Add the new (first) line to the first page of the book. 

     System.out.println("Page1 size: " + book.get(0).size() + "pages"); 
     System.out.println("Page1: " + book.get(0).get(0).getLine()); 

     System.out.println("Page2 size: " + book.get(1).size() + "pages"); 

     if(book.get(1).isEmpty()) //Should book.get(1) should be empty 
     { 
      System.out.println("Page2: EMPTY"); 
     } 
     else 
     { 
      System.out.println("Page2: " + book.get(1).get(0).getLine()); 
     } 
    } 

    public static class PageContents { 
     private String line; 

     public String getLine() { 
      return line; 
     } 

     public void setLine(String line) { 
      this.line = line; 
     } 
    } 
} 

安置自己的完整代码(如果可能)或检查其他方法不修改您的然后我会修改这个答案...

+0

对不起,无法发布整个事情。它有大约1800行。我将代码从一个更大的程序中分离出来以找出问题。我应该在发布之前运行我发布的示例。对于那个很抱歉。我会尽力清理它。问题是,如果上述概念是正确的,那么我就沿着线路将其他东西拧紧了。一切都很好,直到我需要一个新的空白列表添加到书单。 – LazyBear