【问题标题】:Valid iterator on a removed list?已删除列表上的有效迭代器?
【发布时间】:2016-03-15 03:26:15
【问题描述】:

我写了一些有效的代码,但我不确定。考虑

LinkedList<Iterator<Integer>> iterators;
HashMap<Character, TreeSet<Integer>> map;
for (char c : map.keySet()) {
    iterators.add(map.get(c).iterator());
    map.remove(c);
}

即使原始 TreeSet 已被删除,迭代器似乎也能正常工作(即按照 TreeSet 的原始顺序)。我不太明白为什么它是功能性的——似乎这里有按值传递而不是按引用传递。但是,显然,如果我要写

map.get(c).add(6);

TreeSet 实际上会在映射中添加 6(不仅仅是在映射中的 TreeSet 的副本中添加 6),表明 get 是通过引用传递的。有人可以帮助解决这里的困惑吗?

【问题讨论】:

  • 来自TreeSetIteratorHashMap 有什么关系?

标签: java iterator pass-by-value


【解决方案1】:

我看了你的帖子 5 遍了,我还是不明白哪里有问题?

您问为什么在从Map 删除条目后,iterators 中的iterator 仍然可以工作?这就是 Java 中引用的工作原理......

行:

iterators.add(map.get(c).iterator());

创建新的对c 下的TreeSet 的强引用,所以这个set 不会被gced。

当谈到按引用传递与按值传递时 - C/C++ 中没有什么比 真正的按引用传递。详情请看here

说到线:

map.get(c).add(6);

我不知道你的意思是什么

TreeSet 实际上会在地图中添加 6(不仅仅是在地图中的 TreeSet 副本中添加 6)

地图中 TreeSets 的副本是什么意思?什么副本?它指向与 iterator 相同的 TreeSetiterators 指向。

【讨论】:

    【解决方案2】:

    HashMap 中删除TreeSet 不会破坏TreeSet;它只是删除了HashMap 中对TreeSet 的引用。 HashMap 不包含TreeSet 的副本,只是对TreeSet 的引用。

    起初:

    {map} -----> {aTreeSet}
                      |
                      v
                     {6}
    

    Iterator 的目的是迭代某些东西。在这种情况下,它迭代TreeSet 元素的逻辑方法是维护它自己对TreeSet(或TreeSet 中的内部数据结构)的引用。元素总是被至少一个强引用引用,因此它们永远不会被垃圾回收。

    Iterator 创建时:

    {map} -----> {aTreeSet} <----- {Iterator}
                      |
                      v
                     {6}
    

    从地图中移除后(并添加到LinkedList):

    {map}        {aTreeSet} <----- {Iterator} <----- {iterators}
                      |
                      v
                     {6}
    

    总而言之,TreeSet 元素永远不符合垃圾回收条件; TreeSet 对象只有一个,它的元素仍然可以迭代。

    【讨论】:

      猜你喜欢
      • 2016-07-19
      • 1970-01-01
      • 2012-11-11
      • 2017-02-10
      • 2018-07-18
      • 2011-12-21
      • 2013-11-25
      • 2012-02-12
      • 1970-01-01
      相关资源
      最近更新 更多