Scala中的迭代器删除

3

由于迭代器没有删除方法,我该如何将其转换为Scala?
iter的定义如下:

Iterator<Integer> iter = cache.keySet().iterator();

这里的cache是一个哈希表

while (iter.hasNext()) {
        int num = iter.next();
        if (!part.contains(num)){
            iter.remove();
    }
}

1
iter 是如何定义的? - Reimeus
你需要迭代器做什么,为什么不直接使用cache.filter{ case (k, _) => part.contains(k) }过滤cache呢? - Andrey Tyukin
是的,不错的想法,我猜这会起作用。谢谢。 - Suzy Tros
这会删除不包含 num 的元组,对吗? - Suzy Tros
@SuzyTros 这将删除所有键不包含在 part 中的元组。如果我没有漏掉什么,这就是您的迭代器循环所做的事情。请参见下面的可编译示例。 - Andrey Tyukin
@SuzyTros 已更新我的回答。如果你要重复过滤 cache,应该坚持使用 filter,因为 filterKeys 的行为会有很大不同(感谢 @SimY4 指出)。 - Andrey Tyukin
3个回答

5

如果您的实际目标是从缓存中过滤一些键,您可以直接进行操作,无需使用循环和迭代器:

val cache = Map("a" -> 3, "b" -> 5, "c" -> 7)
val part = Set("x", "y", "b")
val filteredCache = cache.filter{ case (k, _) => part.contains(k) }
// prints `Map(b -> 5)`, because "a" and "c" not in `part`
println(filteredCache) 

编辑

正如@SymY4所指出的,filterfilterKeys的行为有很大不同:filter会返回一个新的Map(不可变版本),或将元素就地过滤(可变版本)。然而,filterKeys只构建原始集合的过滤视图。因此,反复调用filterKeys是不可取的,因为它会在其上堆叠更多的视图。

但是,使用filter的解决方案仍应该有效。


在地图上进行大量的过滤最终会使得结果地图变得太慢。我认为最好通过以下方式完全删除键:val updatedCache = cache -- Set("x", "y", "b") - Alex
@SimY4确实,你说的filterKeys是没错的,它并不会创建一个新的集合,而是返回旧集合的视图。这是一个非常棘手的陷阱...非常感谢你指出来! - Andrey Tyukin

1

在地图上进行大量过滤最终会导致结果地图变得过慢。因为您需要在到达实际缓存存储之前应用所有添加的过滤器。我建议使用--语法从地图中删除元素。

scala> Map("a" -> 1, "b" -> 2, "c" -> 3)
res0: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)

scala> res0 -- Set("x", "y", "b")
res1: scala.collection.immutable.Map[String,Int] = Map(a -> 1, c -> 3)

你是怎么得出这个结论的?文档非常明确地说明 filter "返回一个新的可遍历集合,该集合由满足给定谓词 p 的此可遍历集合的所有元素组成。元素的顺序被保留。"(强调我的) - Andrey Tyukin
@AndreyTyukin 你看过实现吗?你会发现filters是原始集合的包装器。这有助于节省一些内存,因为您不必复制整个映射,但最终您的映射将变得非常缓慢。自己试试吧。 - Alex
@AndreyTyukin 我错了,抱歉。filter 的工作方式就像你说的那样。但是 filterKeys 会将所有内容都包装在一个 Filter 包装器中,所以 filterKeys 最终会变慢,而不是 filter - Alex
至少关于filter的说法在2.12.4中是无法复现的。如果我定义了val m = ((0 to 100) zip (400 to 5000)).toMap; val n = m.filter{ case (k, _) => k % 2 == 0 },然后展示m.getClassn.getClass,我会得到scala.collection.immutable.HashMap$HashTrieMap。如果你的Scala做了其他事情,你应该升级到更新的版本或提交一个错误报告。我正在看filterKeys,我不经常使用它,也许我确实错过了什么。 - Andrey Tyukin

0

也许是这样:

val it = Iterator.continually(hashMap.headOption).takeWhile(_.isDefined).flatten
for ((key, value) <- it) {
    hashMap.remove(key)
    ... //do something here with value
}

其中hashMap是一个可变的HashMap实例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接