有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java以object为键通过hashmap进行搜索

我在搜索各种主题,但没有找到任何适合我的情况的解决方案

假设我需要存储以下值: (1) 产品id(2)段id(3)某些价值

(1)和(2)的组合是独一无二的。为了明确起见,让我画一张简单的表格:

| product_id | segment_id | some_value|
---------------------------------------
|      1     |      1     |    100    |
|      1     |      2     |    200    |
|      2     |      1     |    300    |
|      2     |      2     |    400    |

我决定使用带有键的Map作为(1)和(2)的组合。实现该键的类如下(来自其他主题):

class MarketKey {

    private final int x;
    private final int y;

    public MarketKey(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof MarketKey)) return false;
        MarketKey key = (MarketKey) o;
        return x == key.x && y == key.y;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 137 * result + y;
        return result;
    }

}

将值放到地图上效果非常好。现在,我想搜索这些键,并对特定的产品的进行总结,这是键的一部分。如果我知道product_idsegment_id的范围,那就很容易了,但我不知道

我问自己的问题是地图是否是一个好的选择。我之所以选择它,是因为我想确保我不会有两个组合项,即product_idsegment_id,但这扼杀了我搜索密钥元素的能力

有没有关于如何实现这一点的提示

提前谢谢

编辑: 下面的一些答案指出,使用带有产品id的地图作为键。来自java文档:

A map cannot contain duplicate keys; each key can map to at most one value.

如果我的理解是正确的,product_id必须具有唯一的值,在我的示例中,情况并非如此


共 (2) 个答案

  1. # 1 楼答案

    The question I'm asking myself is whether a map is a good choice. I have chosen it because I wanted to make sure that I don't have double entries of combination of product_id and segment_id but this killed my ability to search through the elements of the key.

    Any hint how to implement this?

    你可以用一张地图。顶级映射使用product_id作为其键,每个成员映射使用segment_id

    或者,您可以先基于product_id然后基于segment_id定义键顺序,并使用SortedMapSortedMap.subMap()这样就可以方便地进行您描述的每种产品扫描

    更新:

    对于这种任务,{}的主要优点是实现和使用简单。由headMap()tailMap()subMap()提供的submap视图可以作为一种方便的方式来处理OP呈现的问题类型:

    for (ValueType v : map.subMap(
            new MarketKey(pid, Integer.MIN_VALUE),
            new MarketKey(pid + 1, Integer.MIN_VALUE)).values()) {
        // ... do something with v
    }
    

    ,但使用这种方法,您仍然可以通过一个键访问元素:

    map.put(new MarketKey(pid, sid), myValue);
    

    如果数据大小有一个固定的界限,或者这不是程序的性能关键部分,那么这几乎就是故事的结束。另一方面,如果程序需要执行诸如在其关键路径上描述的操作,并且如果数据可能非常大,则需要考虑性能。与{}或{}的HashMap相比,在SortedMap上进行插入、单独检索和删除的平均性能(O(log n))的扩展效率更低。这是SortedMap的排序性质的必然结果,而不取决于它的特定实现

    对于迭代具有给定产品ID的所有项目,行为如何缩放是一个更复杂的分析,部分取决于每个product_idsegment_id数量如何缩放product_id数量。不管怎样,与HashMapO(1)相比,SortedMap案例的第一个条目有O(log n)成本,但在那之后,剩下的每一个都可以以固定的增量成本获得。如果段ID的数量与产品ID的数量成比例,那么遍历第二个和后续元素的成本占主导地位,并且在每种情况下,总体操作都是O(n)。另一方面,如果段ID的数量是固定的,则HashMap的情况总体上是O(1),而SortedMap的情况是O(log n)

  2. # 2 楼答案

    Map是一个不错的选择,但是使用Map<Integer, Map<Integer, Integer>>是有意义的,其中外部映射的键是产品ID,内部映射的键是段ID

    要获得“一些价值”,你必须

    outerMap.get(productId).get(segmentId);
    

    (实际上,这比这要复杂一些,因为你需要检查null以避免NullPointerException

    优点是,您可以轻松地对特定产品id的值求和:

    int sum = 0;
    for (int someValue : outerMap.get(productId).values())
        sum += someValue;
    

    我相信番石榴有一个Table接口,可以减轻使用这种结构的痛苦,但我从未使用过它。也许值得一看