在C ++中等效的LinkedHashmap?

时间:2017-02-06 16:01:40

标签: c++ unordered-map linkedhashmap

我有一个Java程序,我想将它转换为C ++。因此,Java代码中使用了Linkedhashmap数据结构,我想将其转换为C ++。在C ++中是否有LinkedHashmap的等效数据类型?

我尝试使用std::unordered_map,但是,它不会保持插入的顺序。

4 个答案:

答案 0 :(得分:15)

C ++不提供具有模仿Java LinkedHashMap<K,V>的行为的集合模板,因此您需要与映射分开维护订单。

这可以通过将数据保存在std::list<std::pair<K,V>>中,并保留单独的std::unordered_map<k,std::list::iterator<std::pair<K,V>>>地图,以便按键快速查找项目来实现:

  • 在添加项目时,将相应的键/值对添加到列表的末尾,并将键映射到迭代器std::prev(list.end())
  • 按键删除项目时,查找其迭代器,将其从列表中删除,然后删除映射。
  • 在替换项目时,首先从无序映射中查找列表迭代器,然后用新的键值对替换其内容。
  • 在迭代值时,只需迭代std::list<std::pair<K,V>>

答案 1 :(得分:2)

密钥迭代的插入顺序契约可以通过用于log(n)性能的平衡树来实现。这比维护列表中的键更好,因为项目删除需要n个查找时间。我的口头禅从来没有把你在列表中查找的内容。如果不必排序,请使用哈希。如果应该排序,请使用平衡树。如果您要做的就是迭代,那么列表就可以了。 在c ++中,这将是std::map,其中键是项引用,值是插入顺序,键是使用红黑树排序的。请参阅:Is there a sorted container in STL

答案 2 :(得分:0)

无序映射或用C ++内置的任何其他STL方法不能给出与LinkedHashMap相同的顺序,尽管您可以维护插入的顺序并使用维护的顺序访问unordered_map。

下面的图像只是为了显示unordered_map的行为。它没有订单。

Map是RB树,如果使用迭代器,它会给出排序顺序。

因此没有针对此问题的具体解决方案。

Unordered HashMap

答案 3 :(得分:0)

这是我的方法:

    map<TKey, set<MyClass<K1,K2>, greater<MyClass<K1, K2>>>> _objects; // set ordered by timestamp. Does not guarantee uniqueness based on K1 and K2.
    map<TKey, map<K2, typename set<MyClass<K1, K2>, greater<MyClass<K1, K2>>>::iterator>> _objectsMap; // Used to locate object in _objects

要添加对象id

    if (_objectsMap[userId].find(id) == _objectsMap[userId].end())
       _objectsMap[userId][id] = _objects[userId].emplace(userId, id).first;

要擦除对象id

   if (_objectsMap[userId].find(id) != _objectsMap[userId].end()) {
       _objects[userId].erase(_objectsMap[userId][id]);
       _objectsMap[userId].erase(id);
   }

要检索,请说出从特定对象size开始的列表中最近的id个对象:

    vector<K2> result;
    if (_objectsMap[userId].find(id) != _objectsMap[userId].end() && _objectsMap[userId][id] != _objects[userId].begin()) {
        set<MyClass<K2, K2>, greater<MyClass<K1, K2>>>::iterator start = _objects[userId].begin(), end = _objectsMap[userId][id];
        size_t counts = distance(_objects[userId].begin(), _objectsMap[userId][id]);
        if (counts > size)
            advance(start, counts - size);        
        transform(start,
            end,
            back_inserter(result),
            [](const MyClass<K1, K2>& obj) { return obj.ID(); });
    }
    return result;