A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张 涛 中级黑马   /  2012-9-8 14:48  /  2586 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张 涛 于 2012-9-10 10:54 编辑

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;


public class CollectionDemo {

        public static void main(String[] args) {

                Person p1 = new Person(21);
                Person p2 = new Person(23);
                Person p3 = new Person(21);
               
                HashMap hashMap = new HashMap();
                hashMap.put("zhangsan", p1);
                hashMap.put("lisi", p2);
                hashMap.put("wangwu", p3);
               
                Set set = hashMap.keySet();
                //问题1:hashMap.keySet方法返回一个Set对象,Set是接口,
                //接口可以有引用,并指向其子类对象。但是怎么可以有一个引用set指向自己的对象呢?
                Iterator i = set.iterator();
                while(i.hasNext()){
                        String s = i.next();//这里提示错误,应该把s的类型改为person
                        //问题2:i.next方法应该返回一个String,这里为什么会报错?
                        //并提示应该把s的类型改为person?
                        System.out.println(i.next());//而这里直接打印出的又是person。                        
                }
        }
}

class Person {
        int age;
        Person(int age){
                this.age = age;
        }
        @Override
        public boolean equals(Object obj) {
                Person s = (Person)obj;
                return this.age == s.age;
        }
        @Override
        public String toString() {
                return "Person age = "+ age;
        }
        
}

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

10 个回复

倒序浏览
你注释的有问题,i.next返回的是个object对象,要强制转换为String,你用泛型就可以了;另外你的while循环里面调用两次i.next是不行的,因为你只测试了一次i.hasNext
回复 使用道具 举报
①hashMap.keySet()方法体中就定义了一个建立Set子类的方法, 所以通过该方法调用直接放回的就是一个Set子类,而不是Set类自己的对象
②因为你没有加泛型限定,所以i.next返回的是Object类型的,必须要进行强转或者对迭代器进行类型限定,你这里就限定成String类型

评分

参与人数 1技术分 +1 收起 理由
刘芮铭 + 1 赞一个!

查看全部评分

回复 使用道具 举报
应广驰 发表于 2012-9-8 16:10
①hashMap.keySet()方法体中就定义了一个建立Set子类的方法, 所以通过该方法调用直接放回的就是一个Set子 ...

hashMap.keySet()方法体中定义了一个建立Set子类的方法?

不懂。
回复 使用道具 举报
本帖最后由 张 涛 于 2012-9-8 23:11 编辑
应广驰 发表于 2012-9-8 16:10
①hashMap.keySet()方法体中就定义了一个建立Set子类的方法, 所以通过该方法调用直接放回的就是一个Set子 ...
  1. public Set<K> keySet() {
  2.         Set<K> ks =keySet;//注释
  3.         return (ks != null ? ks : (keySet = new KeySet()));
  4.     }
复制代码
这是我跟踪到hashMap的keySet的方法代码。
问题1:不懂注释部分的keySet哪里来的?
问题2:这是个内部类吗?看不懂,如何有一个Set子类?

都得技术分了,给讲讲呗
回复 使用道具 举报
1)HashMap底层也是用数组,HashSet底层实际上也是HashMap,HashSet类中有HashMap属性(API中查属性)。HashSet实际上为(key.null)类型的HashMap。有key值而没有value值。
接口没有构造方法,所以就不能生成对象。但可引用实现类(在这里正确的说是继承),典型的接口多继承。但是只能使用父类的引用访问父类中的成员(这句是多态的扩展性,也是多态的弊端)。
Set set = new SortedSet();父接口的引用调用子接口的对象,调用父接口的方法(这就是说父接口必须在重多子接口中的功能全,专业术语上说就是功能扩展越界)
SortedSet set =  new SortedSet();(对照类来理解字接口)
总结:我刚写完后感觉出问题了,自己有点晕了,就翻阅资料,共同学习!
2) i.next()返回的是对象(没有指定系统默认就是Object父类对行啊),基于Iterator
Person obj = (Person)i.next();就是向上转型,
加上泛型Iterator<Person>就在遍历时不用指定类型了。
回复 使用道具 举报
//问题1:hashMap.keySet方法返回的是Set一个子类对象,
Iterator i = set.iterator();
while(i.hasNext()){
         String s = i.next();//i.next()获得的是Object对象,这里需要强制转换,应该改成:String s = (String)i.next();
        System.out.println(i.next());//这里应该直接输出s,如果你在打印i.next()将输出第二次迭代的结果。   
回复 使用道具 举报
张 涛 发表于 2012-9-8 22:58
这是我跟踪到hashMap的keySet的方法代码。
问题1:不懂注释部分的keySet哪里来的?
问题2:这是个内部类吗 ...

是的,其实在java的hashMap中还有一个内部类,这个类就是keySet
你可以在你的代码中用 System.out.println(hashMap.keySet().getClass().getName())试试看,
返回的java.util.HashMap$KeySet,这就代表Set通过keySet方法获得的Set对象其实是hashMap的内部类实例

而对于注释部分的keySet,因为keySet其实只需要有一个就可以了,因为每个hashMap集合只可能有一种key队列,多了就浪费空间了,所以除了第一次会new一个新的对象,你再次调用,就把以前已经创建的keyset对象给你
回复 使用道具 举报
lz,我简单的说一说,
while(i.hasNext()){
                 String s = (String) i.next
//你强制转换一下就行了,
                               System.out.println(s);     
//跟上面是同一个原因,你输出接收到的s就可以啦               
         }
回复 使用道具 举报
第一个问题就更简单啦,hashMap.get("zhangsan");这样就OK了;
希望对lz有所帮助
回复 使用道具 举报
明白了,是有一个keySet类,它继承了AbstractSet<K>,jdk中的源码如下:
  1. public Set<K> keySet() {
  2.         Set<K> ks = keySet;
  3.         return (ks != null ? ks : (keySet = new KeySet()));
  4.     }

  5.     private final class KeySet extends AbstractSet<K> {
  6.         public Iterator<K> iterator() {
  7.             return newKeyIterator();
  8.         }
  9.         public int size() {
  10.             return size;
  11.         }
  12.         public boolean contains(Object o) {
  13.             return containsKey(o);
  14.         }
  15.         public boolean remove(Object o) {
  16.             return HashMap.this.removeEntryForKey(o) != null;
  17.         }
  18.         public void clear() {
  19.             HashMap.this.clear();
  20.         }
  21.     }
复制代码
扫噶,明白了,谢谢。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马