Java:我应该使用哪种集合类型?

时间:2015-03-11 13:04:24

标签: java performance collections hashmap

我需要的是:

  • 最快放/放,这个用了很多。
  • 迭代,也经常使用。
  • 持有一个物体,例如播放器。删除应该是o(1)所以也许是hashmap?
  • 没有重复的密钥
  • 从不使用直接get(),主要是迭代来检索数据 .`

我不担心记忆,我只想以最快的速度行事,即使它以记忆为代价。

6 个答案:

答案 0 :(得分:1)

对于迭代,没有什么比普通的旧数组更快。条目按顺序保存在内存中,因此JVM只需将一个条目的长度添加到其地址即可到达下一个条目。

与地图或列表相比,数组处理通常有点麻烦(例如:没有字典式查找,固定长度)。但是,在你的情况下,我认为使用一维或二维数组是有意义的,因为数组的长度不会改变,也不需要字典式的查找。

答案 1 :(得分:0)

因此,如果我理解正确,你想拥有一个二维网格,其中包含哪些玩家在特定区块中的信息?对我而言,它听起来并不像你应该删除或添加到网格中的东西。我只想使用一个包含Player类型或类似东西的二维数组。然后,如果区块中没有玩家,您可以将该位置设置为null,或者设置一些静态值,如Player.none()或Tile.empty(),或者您想要实现它。无论哪种方式,一个简单的二维数组应该可以正常工作。 :)

答案 2 :(得分:0)

您案例的最佳收藏品是LinkedList。链接列表将允许快速迭代,并在链表中的任何位置快速删除和添加。例如,如果使用ArrayList,并且可以在索引i处插入内容,则必须将所有元素从i移动到右边的一个条目。如果要删除,也会发生同样的情况。在链接列表中,您可以在固定时间内添加和删除。

由于您需要两个维度,因此可以在链接列表中使用链接列表:

List<List<Tile> players = new LinkedList<List<Tile>>(20);
for (int i = 0; i < 20; ++i){
   List<Tile> tiles = new LinkedList<Tile>(20); 

   for (int j = 0; j < 20; ++j){
       tiles.add(new Tile());
   }   

   players.add(tiles);
}

答案 3 :(得分:0)

使用集合映射保证O(1)用于顶点查找和摊销O(1)复杂性边缘插入和删除。

HashMap<VertexT, HashSet<EdgeT>> incidenceMap;

答案 4 :(得分:0)

没有简单的“一刀切”的解决方案。

例如,如果想要追加,迭代并使用Iterator.remove(),则有两个明显的选项:ArrayListLinkedList

  • ArrayList占用的内存较少,但Iterator.remove()O(N)

  • LinkedList使用更多内存,但Iterator.remove()O(1)

如果你还想快速查找; (例如Collection.contains测试),或使用Collection.remove删除,然后HashSet会更好......如果集合可能很大。 HashSet不允许您多次将对象放入集合中,但这可能是一个优势。它还使用比ArrayListLinkedList更多的内存。

如果您对所需的属性更具体,以及您正在优化的内容(速度,内存使用,两者?)那么我们可以为您提供更好的建议。

答案 5 :(得分:0)

不允许重复的要求实际上增加了对高效get()的要求。

您的选项可以是基于散列的,也可以是O(Log(N))。最有可能的是,hashcode会更快,除非出于某种原因,调用hashCode()+ equals()一次比调用compareTo()Log(N)次要慢得多。例如,如果您处理非常长的字符串,则可能是这样。顺便说一下Log(N)不是很多:Log(1,000,000,000)〜= 30。

如果您想使用基于散列的数据结构,那么HashSet就是您的朋友。确保Player具有hashCode()的快速实现。如果您提前知道条目数,请指定HashSet大小。 (ceil(N / load_factor)+1。默认加载因子是0.75)。

如果要使用基于排序的结构,请实现高效的Player.compareTo()。您的选择是TreeSet或Skip List。它们在特征方面具有相当的可比性。 TreeSet非常好用,它在JDK中可以直接使用,而只有一个并发的SkipList可用。两者都需要在添加数据时重新平衡,这可能需要时间,而且我不知道如何预测哪个更好。