将 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 Iteger0吗?你不需要做类似的事情吗:

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};

我想我最初的尝试在某种程度上是不正确的,但它工作得很好,所以也许它会在将来帮助其他人。