C++ equivalent to Java Map getOrDefault?

C++ equivalent to Java Map getOrDefault?

本文关键字:getOrDefault Map Java equivalent to C++      更新时间:2023-10-16

Java的getOrDefault是一个很好的结构,用于一行访问映射值或起点(如果不存在(。 我在地图参考中没有看到任何内容C++与平行。 是否存在某些东西还是构建自己的东西?

我在地图中有对象,如果它们存在,我会更新它们,但如果它们不存在,我会构造新的对象。使用 getOrDefault,我可以在默认端构造对象,或者访问它(如果存在(。

http://www.cplusplus.com/reference/map/map/

https://www.geeksforgeeks.org/hashmap-getordefaultkey-defaultvalue-method-in-java-with-examples/

我在地图中有对象,如果存在,我会更新它们,但是 如果他们不这样做,则构建新的。使用 getOrDefault,我可以构造 对象,或者访问它(如果存在(。

使用emplace.

auto& element = *map.emplace(key, value).first;

如果键不存在,emplace插入一个新元素,并返回一对,该元素的迭代器(插入或已存在(和一个指示是否进行了插入的bool值组成。

当我试图找出一种在C++中使用HashTable解决LeetCode单数问题的方法时,我来到了这里。

在方法 2 和 Java 中使用的 getOrDefault 没有直接的替代方案,但我能够使用 operator[] 来访问unordered_map的元素。 参见 http://www.cplusplus.com/reference/unordered_map/unordered_map/operator[]/

如果映射中存在该键,则运算符 [] 将返回对其映射值的引用。

如果键不存在,则运算符 [] 会将键添加到映射中,值为 0。

当您尝试递增键的值(如果已存在(或向映射添加新键(如果不存在(时,这可能很有用。

例如,我在C++中使用了以下内容

for (int i : nums) { hash_table[i] = hash_table[i] + 1; }

这是 Java 中以下内容的替代方案

for (int i : nums) { hash_table.put(i, hash_table.getOrDefault(i, 0) + 1); }

L.F 的答案是使用map::emplace是映射的值类型不需要构造函数时要走的路,因为每次调用构造函数时都如下例所示。

C++17附带insert_or_assign略有不同。

可能最有效的解决方案是执行以下操作:

template <class M, class Vp>
std::pair<typename M::iterator, bool> insert_or_create(M& map, typename M::key_type&& k, Vp&& v) {
auto p = map.lower_bound(k);
if (p != map.end()) {
return std::make_pair(p, false);
}
return std::make_pair(map.emplace_hint(p, std::move(k), std::forward<Vp>(v)), true);
}

下面是一个显示其工作原理的示例:

#include <sstream>
#include <iostream>
#include <string>
#include <map>
class Element {
public:
Element(int value) : value(value) {
std::cout << "Element ctor value = " + std::to_string(value) << std::endl;
}
int value;
};

template <class M, class Vp>
std::pair<typename M::iterator, bool> insert_or_create(M& map, typename M::key_type&& k, Vp&& v) {
auto p = map.lower_bound(k);
if (p != map.end()) {
return std::make_pair(p, false);
}
return std::make_pair(map.emplace_hint(p, std::move(k), std::forward<Vp>(v)), true);
}
int main(int argc, char **argv) {
std::map<int, Element> map;
auto& e1 = *map.emplace(1, Element(1)).first;
std::cout << "Element in map: " << std::to_string(e1.second.value) << std::endl;
auto& e11 = *map.emplace(1, Element(11)).first;
std::cout << "Element in map: " << std::to_string(e11.second.value) << std::endl;
auto e2 = *map.insert_or_assign(2, 2).first;
std::cout << "Element in map: " << std::to_string(e2.second.value) << std::endl;
auto e22 = *map.insert_or_assign(2, 22).first;
std::cout << "Element in map: " << std::to_string(e22.second.value) << std::endl;
auto e3 = *insert_or_create(map, 3, 3).first;
std::cout << "Element in map: " << std::to_string(e3.second.value) << std::endl;
auto e33 = *insert_or_create(map, 3, 33).first;
std::cout << "Element in map: " << std::to_string(e33.second.value) << std::endl;
}

产生

Element ctor value = 1
Element in map: 1
Element ctor value = 11       <-- calling ctor, not optimized away   
Element in map: 1             <-- still old value in map as expected 
Element ctor value = 2
Element in map: 2
Element ctor value = 22       <-- calling ctor  
Element in map: 22            <-- new value assigned to key 2, as expected
Element ctor value = 3
Element in map: 3             <-- ctor not called as wanted!!!!!!   
Element in map: 3

这表明insert_or_create没有调用Element的构造函数。

我不确定为什么这样的函数不在 std::map 接口中,因为它非常有用。

也许我误解了你在问什么,但这就是map的工作方式。

map<int, string> m;
string s = m[3];

s设置为默认构造的string

当您使用operator[]在地图中查找键时,它始终会返回一个值。如果映射中不存在该键,它将使用默认构造值插入它。

如果你想要这种行为,但使用不同的值(不是默认构造的值(,那么你可以使用emplace,正如 L.F. 所建议的那样。

  • Java

map.put(sum, map.getOrDefault(value, 0) + 1);
  • C++ 中的等效代码

auto it1 = map.find(value);
if (it1 != um.end())
map[value]++;
else
map[value] = 1;

我认为以下是您要查找的内容

mymap.emplace(key, DEFAULT_VALUE).first->second = value;

如以下示例中使用的

#define DEFAULT_VALUE 0
map<int,int> mymap;
mymap[1] = 1;
// mymap is having some entries.
// will increment existing element.
mymap.emplace(1,DEFAULT_VALUE).first->second++; 
// will insert a new element with key 2 and value as default(0), than increment it.
mymap.emplace(2,DEFAULT_VALUE).first->second++;