小弟看书自学,看到java集合这里有点疑问,想了很久也上机试了还是搞不明白,求大神们指点!
import java.util.*;
public class IteratorTest
{
public static void main(String[] args) 
{
Collection books = new HashSet();
books.add(new String("Java EE"));
books.add(new String("IOS"));
books.add(new String("Android"));
System.out.println(books);
Iterator it = books.iterator();
String b = (String)it.next();   //①
b = "aaa";
System.out.println(books);
}
}
这段代码是我用书上的范例改了改,运行结果如下:
[Android, IOS, Java EE]
[Android, IOS, Java EE]对应的这段代码书上是这么讲解的:
当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响。
所以我理解①处的b只是一个迭代变量,修改它并不会影响集合。接着是这段代码:
import java.util.*;
public class Test {
private String a;
public Test(String a){
this.a = a;
}
public String toString(){
return "["+a+"]";
}
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new Test("java"));
hs.add(new Test("c++"));
hs.add(new Test("ruby"));
System.out.println(hs);
//取出第一个元素
Iterator it = hs.iterator();
Test first = (Test)it.next();
//为第一个元素的a实例变量赋值
first.a = "C#";
System.out.println(hs);
}
}
这是书上的代码,结果如下:
[[java], [c++], [ruby]]
[[C#], [c++], [ruby]]于是我的疑问就来了:这两段代码的区别无非是第一个用的String,第二个手动写了个类,修改的是类成员。为什么第二段代码用next()就能取出元素并修改。第一个不也是取出元素了吗,为啥修改了最后的结果又没有修改到集合呢?
于是我猜想,因为集合是保存的对象,而第一代码是修改的对象,第二个是修改的对象成员。是不是不能修改对象呢,只能修改对象成员呢?但是感觉这个猜想也不对,因为第一段代码书上说通过it.next()只是值传递,把值给了迭代变量,按照书上这段话理解,第一段代码的b和第二段代码的first只是迭代变量,修改它都不应该会对集合元素造成影响啊。为什么第二段代码又能修改了??
我晕了
求大神指点!谢谢!!Java集合

解决方案 »

  1.   

    String b = (String)it.next();   //①
    这里传给b的是String型的值
    那么这里的b应该是一个新的对象。//楼主可以做个实验试试,看看hashcode是不是一样的。
    Test first = (Test)it.next();
    这里应该传入的是地址值吧。
    传入的是地址值,如果你只是对这个地址值进行修改的话,我估计也不影响原对象,
    但是如果你对这个地址值上的值进行修改,那应该就不行了吧。个人感觉,有错请指出。。
      

  2.   

    这不能证明这个问题吧,感觉这个例子本身有问题
    String b = "aaa";创建了一个新的“aaa”对象,将使引用 b指向他,
    执行完后,引用b表示了另一个对象,和原对象一点关系都没有
    怎么可以证明
     “当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响。”
    而System.out.println(hs);        
    //取出第一个元素        
    Iterator it = hs.iterator();        
    Test first = (Test)it.next();        
    //为第一个元素的a实例变量赋值        
    first.a = "C#";        
    System.out.println(hs);
    这段代码说明:
    (Test)it.next(); 是一个引用,指向堆中的内存地址,因为执行完以下两句
    Test first = (Test)it.next(); 
    first.a = "C#";   
    对first的修改,表现到了集合中的对象
    因此可以肯定it.next(); 返回的是一个对象引用
    求大神详解啊!!!!  
      

  3.   

    当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给了迭代变量,而是把集合元素的值传给了迭代变量,所以修改迭代变量的值对接元素本身没有任何影响这句话要怎么理解?
      

  4.   

    集合存储的是对象的存储地址,第一个例子中b变量拿到的是其实是对象的引用,修改变量b是不会修改对象的.但第二个例子first.a = "C#",first拿到的是对象的引用,然后first.a对对象的成员变量赋值所以改变了对象里的内容,最终打印的结果会改变.
      

  5.   

    正解。
    这样理解楼主在书中看到的那一句:通过迭代器遍历集合时,返回的的确是集合中的一个元素值,只不过这个值就是元素的引用(地址),基于#4楼的解释,改变引用不会对元素造成影响。而你的第二个例子并不是“改变值”,而是改变了“值”(引用)指向的那个对象的“状态”(此例中你是改变了一个属性),因此你的第二个例子并不恰当。
    第二个例子应该改成这样:first.a = "C#";——> first = new Test("C#");
    结果依然佐证了那句话想表达的意思。此外,lz看到的书中的这句话,把“Iterator并不是把集合元素本身传给了迭代变量”这句去掉,理解剩下的就比较清晰了。