2011-12-09 32 views
3

在游戏中,我需要保持选项卡中我正在使用哪些池中的精灵。当“主动”多个精灵一次我想从我的passivePool转移到activePool这两个都是不可变的HashSets(好吧,我会创建新的集合,每次确切)。所以我的基本思路是沿着线:在Scala中将实例从Set移动到另一个

activePool ++= passivePool.take(5) 
passivePool = passivePool.drop(5) 

但阅读斯卡拉文档我猜,我拿5可能会有所不同的是,5我再落。这绝对不是我想要的。我也可以这样说:

val moved = passivePool.take(5) 
activePool ++= moved 
passivePool --= moved 

,但因为这是我需要做实时几乎每帧一个有限的设备(Android手机),我想这将是我将不得不寻找更慢上从passivePool一个接一个地每个moved精灵。

任何聪明的解决方案?或者我错过了一些基本的东西?记住效率是这里主要关心的问题。我无法使用列表而不是集合,因为当游戏中的精灵被破坏时,我还需要从activePools中随机访问精灵。

+1

1.为什么你认为第一个版本比第二个版本更有效率?我建议为你的问题使用可变映射。这只是一种感觉。 – ziggystar

回答

6

没有什么比得到这些问题的答案的基准。让我们拿100套1000尺寸的产品,一次放5颗,直到它们变空,然后看看需要多长时间。

passivePool.take(5); passivePool.drop(5)     // 2.5 s 
passivePool.splitAt(5)          // 2.4 s 
val a = passivePool.take(5); passivePool --= a    // 0.042 s 
repeat(5){ val a = passivePool.head; passivePool -= a }  // 0.020 s 

这是怎么回事?

这种方式工作的原因是,immutable.HashSet被构建为一个散列优化(有效地O(1))添加和删除操作,但许多其他方法不重新实现;相反,它们是从不支持添加/删除的集合继承的,因此无法获得免费的有效方法。因此他们大多从零开始重建整个哈希集合。除非你的哈希集只有少数几个元素,否则这是个坏主意。 (相对于大小为1000的集合减少50-100倍,一组大小为100的“仅”为6-10倍的减速....)

因此,底线:直到图书馆得到改进,它是“低效率”的方式。你会很快更快

+0

谢谢你,这非常有趣和令人惊讶!是的,我特别想到斯卡拉的作品,我不应该尝试使用常识,而应该采取相反的措施。 – vertti

4

我认为有可能是在这里使用splitAt一些里程,它会给你回两个五个精灵移动和在一个单一的方法调用中的修整池:

val (moved, newPassivePool) = passivePool.splitAt(5) 
activePool ++= moved 
passivePool = newPassivePool 

奖励积分,如果你能分配直接返回到第一行的passivePool,尽管我不认为在定义新变量moved的简短示例中这是可能的。

+0

我知道必须有类似的分区,但只是采取/下降。谢谢! – vertti

相关问题