HashMap调用keySet()是怎么得到set集合的?

Nisus-LJ 2017-09-08 03:56:21

## 问题描述

我们知道要获取HashMap中key可以调用keySet(方法), 可是我通过看源码, 发现该代码仅仅是返回一个KeySet对象, 并没有没有写构造方法, 没有对应的方法获取key, 但是一旦调用这个方法, 接受的set里就已经有值, 那么这个值是哪里来的呢?


	
public static void main(String[] args) throws IOException {

HashMap<Integer, String> hm = new HashMap<Integer, String>();
//添加测试数据
hm.put(1, "a");
hm.put(2, "b");
hm.put(3, "c");

//调用keySet()方法得到set集合
Set<Integer> key = hm.keySet(); //这里只是返回一个KeySet对象, 为什么就已经有值了?
System.out.println(key);
//==>[1, 2, 3] 这里输出了key值的集合, 说明调用keySet方法就已经得到了这个集合

}




Set<Integer> key = hm.keySet(); debug>>
    public Set<K> keySet() {
Set<K> ks = keySet;
return (ks != null ? ks : (keySet = new KeySet())); //返回一个KeySet对象
}


再来看KeySet类
private final class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return newKeyIterator();
}
public int size() {
return size;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return HashMap.this.removeEntryForKey(o) != null;
}
public void clear() {
HashMap.this.clear();
}
}


类代码中可见, KeySet 没有具体写构造方法, 那么应该默认有个空参构造方法, 父类中也没有找打相应的方法.

问题可能描述的不清楚, 请多包涵!
...全文
1135 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
chho93 2017-09-28
  • 打赏
  • 举报
回复
  public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }
返回了一个 new KeySet(); 你直接打印 key 其实是打印 KeySet 的toString(),KeySet 的父类的父类, 的toString() 如下;
 public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
里面调用了iterator(); 方法。 仔细看 iterator() 是个抽象方法 所以, 向下找 AbstractCollection<E> 的 子类, 发现 keySet 重写了iterator();
 public final Iterator<K> iterator()     { return new KeyIterator(); }
它返回的是 new KeyIterator() ; 然后再看 new KeyIterator();
final class KeyIterator extends HashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().key; }
    }
然后 自己看吧!!!下班了
Nisus-LJ 2017-09-27
  • 打赏
  • 举报
回复
我去, 这个不能单独回复?? @huhk 我这个代码调试, keyset是null的, 哪里来的所以不太重要.
  • 打赏
  • 举报
回复
你可以看下他的方法返回时调用的方法:调用的都是HashMap的方法。实际上仍然是在借助这个Set操作HashMap。
huhk 2017-09-11
  • 打赏
  • 举报
回复
楼主看看 Set<K> ks = keySet; 这句的keySet是哪里来的吧,没有参数传进来。所以是已经有的类属性。有赋值过了吧 public Set<K> keySet() { Set<K> ks = keySet; return (ks != null ? ks : (keySet = new KeySet())); //返回一个KeySet对象 }
alexqiaodan 2017-09-10
  • 打赏
  • 举报
回复
对于楼主关于没有构造器的疑问,我觉得可以去看下父类的构造器,或者在上面的父类。理论上是绝对存在的
坤哥玩csdn 2017-09-08
  • 打赏
  • 举报
回复
HashMap中的keySet方法返回的是HashMap中的KeySet类对象.这个类在HahMap中实现.可以看其中的各个方法比如size.返回的是HashMap对象的size.,其他方法也是,也就是说这个set中的任何方法返回的数据都是调用的map的数据获得的

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧