将 Java LinkedHashMap 转换为 C++ std::map
Converting Java LinkedHashMap to C++ std::map
我正在尝试将程序从 Java 移植到 C++,但我似乎无法弄清楚如何将 LinkedHashMap 转换为 std::map。我无法更改 LinkedHashMap,但我不限于 std::map。我需要它来生成相同的 key/value 对,但 ordering/hashing/whatever 其他并不重要。
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 个元素,因此它似乎正确地遍历了潜在的键。
我不确定从这里到哪里去。我尝试过重载运算符、自定义比较器、自定义哈希函数等,但我一定遗漏了一些东西。
在 java
版本的新地图项目中,您将 v
设置为 0
,然后在将其放入地图时添加 1
。 \在 C++
版本中你把它放在 0
.
Java
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
中不存在一个键,当您使用 pointMap[pt]
访问它时,会自动创建一个键(具有相应的值 0
)。所以你可以增加,新值将从 1
开始,就像在 Java
代码中一样。
切换到无序映射、使用自定义哈希函数并重载 == 运算符就成功了
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};
我想我最初的尝试在某种程度上是不正确的,但它工作得很好,所以也许它会在将来帮助其他人。
我正在尝试将程序从 Java 移植到 C++,但我似乎无法弄清楚如何将 LinkedHashMap 转换为 std::map。我无法更改 LinkedHashMap,但我不限于 std::map。我需要它来生成相同的 key/value 对,但 ordering/hashing/whatever 其他并不重要。
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 个元素,因此它似乎正确地遍历了潜在的键。
我不确定从这里到哪里去。我尝试过重载运算符、自定义比较器、自定义哈希函数等,但我一定遗漏了一些东西。
在 java
版本的新地图项目中,您将 v
设置为 0
,然后在将其放入地图时添加 1
。 \在 C++
版本中你把它放在 0
.
Java
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
中不存在一个键,当您使用 pointMap[pt]
访问它时,会自动创建一个键(具有相应的值 0
)。所以你可以增加,新值将从 1
开始,就像在 Java
代码中一样。
切换到无序映射、使用自定义哈希函数并重载 == 运算符就成功了
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};
我想我最初的尝试在某种程度上是不正确的,但它工作得很好,所以也许它会在将来帮助其他人。