我正在尝试将程序从Java移植到C ++,我似乎无法弄清楚如何将LinkedHashMap转换为std :: map。我无法更改LinkedHashMap但我不限于std :: map。我需要它来生成相同的键/值对,但订购/散列/其他任何不重要的事情。
要转换的Java代码:
List<Face> faces = new ArrayList<Face>(modelFull.faces.length);
Map<Point3D, Integer> map = new LinkedHashMap<Point3D, Integer>();
for (int i = 0; i < modelFull.faces.length; i++) {
Face f = new Face(modelFull.faces[i]);
faces.add(f);
for (int k = 0; k < 3; k++) {
Point3D p = f.pts[k];
Integer v = map.get(p);
if (v == null) {
v = 0;
}
map.put(p, v + 1);
}
}
我的尝试:
std::map<RVPoint3D, int> pointMap;
auto modelFaces = modelFull.getFaces();
for (const auto &face : modelFaces)
{
Face newFace = Face(face);
for (int k = 0; k < 3; ++k)
{
RVPoint3D pt = newFace.getPts()[k];
++pointMap[pt];
}
faces.push_back(newFace);
}
Java实现创建了一个大小为7523的映射,而C ++的映射为7967.两者共检查了45234个元素,因此它似乎正在通过潜在的密钥正确迭代。
我不知道从哪里开始。我已经尝试过载运算符,自定义比较器,自定义哈希函数等,我必须遗漏一些东西。
答案 0 :(得分:0)
在新版地图项的java
版本中,您将v
设置为0
,然后在将其放入地图时将1
添加到其中。在C++
版本中,您将其放入0
。
<强>爪哇强>
Integer v = map.get(p);
if (v == null) {
v = 0;
}
map.put(p, v + 1); // new map entries go in as 1
<强> C ++ 强>
if (pointMap.count(pt))
{
pointMap[pt] += 1;
} else {
pointMap[pt] = 0; // new map entries go in as 0
}
您还可以在Java中设置null
Iteger
到0
吗?你不需要做类似的事情:
v = new Integer(0); // ?
旁注:
C++
代码可以改写为:
for (const auto &face : modelFaces)
{
Face newFace(face); // Value, no need for Java-like syntax
for (int k = 0; k < 3; ++k)
{
RVPoint3D pt = newFace.getPts()[k];
++pointMap[pt]; // auto sets to 1 on new entry
}
faces.push_back(newFace);
}
这是有效的,因为如果std::map
中不存在某个密钥,则在使用0
访问密钥时会自动创建(具有相应的值pointMap[pt]
)。因此,您只需递增,新值将从1
开始,就像在Java
代码中一样。
答案 1 :(得分:0)
使用自定义散列函数切换到无序映射,并重载==运算符可以解决这个问题
auto hashCode = [](const RVPoint3D pt)
{
return pt.x + pt.y + pt.z;
};
std::unordered_map<RVPoint3D, int, std::function<double(RVPoint3D)>> pointMap{modelFull.getFaces().size(), hashCode};
我想我最初的尝试在某种程度上是不正确的,但这完全有效,所以也许它将来会帮助别人。