等价于 C++ 中的 LinkedHashmap?
equivalent LinkedHashmap in C++?
我有一个 Java 程序,我想将它转换为 C++。因此,Java 代码中使用了一个 Linkedhashmap
数据结构,我想将其转换为 C++。 LinkedHashmap
在 C++ 中是否有等效的数据类型?
我尝试使用std::unordered_map
,但是,它不保持插入的顺序。
C++ 不提供具有模仿 Java 的 LinkedHashMap<K,V>
行为的集合模板,因此您需要从映射中单独维护顺序。
这可以通过将数据保存在 std::list<std::pair<K,V>>
中并保存一个单独的 std::unordered_map<k,std::list::iterator<std::pair<K,V>>>
映射来实现,以便通过按键快速 look-up 项目:
- 添加项目时,将相应的 key/value 对添加到列表的末尾,并将键映射到迭代器
std::prev(list.end())
.
- 按键删除项目时,查找其迭代器,将其从列表中删除,然后删除映射。
- 替换项目时,首先从无序映射中查找列表迭代器,然后用新的 key-value 对替换其内容。
- 在迭代值时,只需迭代
std::list<std::pair<K,V>>
.
密钥迭代的插入顺序契约可以通过平衡树实现 log(n) 性能。这比在列表中维护键要好,因为删除项需要 n 次查找时间。我的口头禅是永远不要把你查找的东西放在列表中。如果不需要排序,请使用哈希。如果应该排序,请使用平衡树。如果您要做的只是迭代,那么列表就可以了。
在 C++ 中,这将是 std::map
,其中键是项目引用,值是插入顺序,键使用 red-black 树排序。参见:Is there a sorted container in STL
我是这样做的:
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);
}
要检索,例如从特定对象 id
开始的列表中最近的 size
个对象:
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;
我有一个 Java 程序,我想将它转换为 C++。因此,Java 代码中使用了一个 Linkedhashmap
数据结构,我想将其转换为 C++。 LinkedHashmap
在 C++ 中是否有等效的数据类型?
我尝试使用std::unordered_map
,但是,它不保持插入的顺序。
C++ 不提供具有模仿 Java 的 LinkedHashMap<K,V>
行为的集合模板,因此您需要从映射中单独维护顺序。
这可以通过将数据保存在 std::list<std::pair<K,V>>
中并保存一个单独的 std::unordered_map<k,std::list::iterator<std::pair<K,V>>>
映射来实现,以便通过按键快速 look-up 项目:
- 添加项目时,将相应的 key/value 对添加到列表的末尾,并将键映射到迭代器
std::prev(list.end())
. - 按键删除项目时,查找其迭代器,将其从列表中删除,然后删除映射。
- 替换项目时,首先从无序映射中查找列表迭代器,然后用新的 key-value 对替换其内容。
- 在迭代值时,只需迭代
std::list<std::pair<K,V>>
.
密钥迭代的插入顺序契约可以通过平衡树实现 log(n) 性能。这比在列表中维护键要好,因为删除项需要 n 次查找时间。我的口头禅是永远不要把你查找的东西放在列表中。如果不需要排序,请使用哈希。如果应该排序,请使用平衡树。如果您要做的只是迭代,那么列表就可以了。
在 C++ 中,这将是 std::map
,其中键是项目引用,值是插入顺序,键使用 red-black 树排序。参见:Is there a sorted container in STL
我是这样做的:
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);
}
要检索,例如从特定对象 id
开始的列表中最近的 size
个对象:
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;