Java中列表的不稳定行为

时间:2010-08-21 08:50:38

标签: java list

我在java中的数据对象中有一个列表,其中包含从数据库中检索的数据,无论是多行还是单行。我从BO中检索List并将其转储到临时列表中,以便我可以迭代它以提取数据。当我在完成第一次分配后检查列表的大小时,一切都很顺利,但是当我尝试在for循环中迭代列表时,它的大小正在减小。我在列表中测试了两行数据,但在厕所中,它的大小始终是一个。有趣的是,我在很多地方已经多次使用过这种逻辑,但是在我写这篇文章的业务流程中,它表现得非常不稳定。有没有任何线索?这是一个示例代码

List temp = new ArrayList();

temp = dummyBO.getList(0) // Retrieves the List at index 0 from the BO

//Imagine the list has 2 rows of data. This prints the size as 2
System.out.println("size: "+temp.size());

System.out.println("Contents: "+temp.get(0);
System.out.println("Contents: "+temp.get(1);

//This is where the List starts behaving erratically

**for(int i=0;i<temp.size();i++){
     System.out.println("size: "+temp.size()); //here the size is displayed as 1
     System.out.println("Contents: "+temp.get(i); // here only the data at index 0 is shown
}**

P.S。此Java代码编写在IBM WID 6.1的代码段部分中

3 个答案:

答案 0 :(得分:3)

你说:

  

我从BO中检索List并将其转储到临时列表中

你的片段说:

// original snippet
List temp = new ArrayList();    
temp = dummyBO.getList(0);

绝对肯定地说这是不可能的,但这是一种代码气味,并且极有可能是造成问题的错误。

臭臭的部分是你创建了一个new ArrayList,但它立刻就变成了垃圾。此代码段不会使用ArrayList列表中的元素填充dummyBO。它将temp设置为引用新创建的对象,但随后它会释放该对象以完全引用其他内容。请记住,对象的=只是Java中的引用赋值;它不能超载以做任何不同的事情。

也许你想要这样的东西:

// possible fix #1
List temp = new ArrayList(dummyBO.getList(0));

这实际上会创建一个new ArrayList,并使用从dummyBO获得的列表元素填充该列表。这使用ArrayList(Collection)构造函数,它遍历Collection并将其元素添加到列表中。

或者您也可以这样做:

// possible fix #2
List temp = new ArrayList();
temp.addAll(dummyBO.getList(0));

答案 1 :(得分:2)

我怀疑这个

temp = dummyBO.getList(0)

引用检索到列表,而不是副本。因此无论为您提供此引用,都可以随意更改该列表。你需要采取这份清单的防御性副本吗?

答案 2 :(得分:0)

正如其他答案所说,你需要复制列表的内容。

但是你的问题比这更深刻。很明显,另一个线程正在改变列表的内容。简单地复制getList(0)返回的列表并不可靠。复制时,另一个线程可能会更改列表!

相反,您需要更改getList(int)方法,以便 it 创建列表的副本,它会保持锁定以停止列表在被复制时被更改。

修改

可以使用复制构造函数创建列表副本;例如根据@polygenelubricants的回答使用new ArrayList(someList)

但是没有简单的答案来锁定列表以在复制时阻止列表被更改。这取决于访问和更新列表的其他内容......以及如何。