使用对象作为键搜索hashmap

时间:2015-10-11 21:49:41

标签: java hashmap

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

我们假设我需要存储以下值: (1) product_id (2) segment_id (3) some_value

(1)和(2)的组合是唯一的。为了说清楚,让我画一个简单的表格:

$fileName = "export.xls";

$data = View::make('export.excel.table', [
    'thead' => $thead,
    'tbody' => $tbody,
    'tfoot' => $tfoot,
]);

return Response::make($data, 200, [
    'Content-type'        => 'application/excel',
    'Content-Type'        => 'application/excel',
    'Content-Disposition' => 'attachment; filename=' . $fileName
]);

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

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

将值放到地图上的效果非常好。现在,我想搜索密钥并总结 some_value 以获取特定的 product_id ,这是密钥的一部分。如果我知道 product_id segment_id 的范围,那将很容易,但我不知道。

我问自己的问题是地图是否是一个不错的选择。我选择它是因为我想确保我没有 product_id segment_id 组合的双重条目,但是这使我无法搜索元素关键。

任何提示如何实现这个?

提前致谢。

修改 下面的一些答案指出使用 product_id 作为关键字的地图图。来自java doc:

  

地图不能包含重复内容   键;每个键最多可以映射一个值。

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

3 个答案:

答案 0 :(得分:2)

  

我问自己的问题是地图是否是一个不错的选择。我之所以选择它是因为我想确保我没有使用product_id和segment_id组合的双重条目,但是这使我无法搜索密钥的元素。

     

任何提示如何实现这个?

您可以使用地图地图。顶级地图使用product_id作为其键,每个成员地图使用segment_id

或者,您可以先根据product_id然后segment_id定义一个关键订单,然后使用SortedMap。然后,SortedMap.subMap()便于您描述的每种产品扫描。

<强>更新

SortedMap对此类任务的主要优点是实现和使用的简单性。 headMap()tailMap()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);

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

迭代具有给定产品ID的所有项目的行为规模如何进行分析是非常棘手的,部分取决于segment_idproduct_id个数量与product_id数量的比例秒。无论如何,O(log n)案例的第一个条目的成本为SortedMap,而O(1)的{​​{1}}成本为HashMap,但之后可以获得剩余的一个固定增量成本。如果段ID的数量与产品ID的数量成比例,那么迭代第二个和后续元素的成本占主导地位,并且在每种情况下整体操作为O(n)。另一方面,如果段ID的数量是固定的,则HashMap案例总体上为O(1),但SortedMap案例为O(log n)

答案 1 :(得分:1)

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

获得&#34; some_value&#34;你必须要做

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

(实际上它比你需要检查null以避免NullPointerException)复杂一点。

优点是您可以轻松汇总特定产品ID的值:

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

我相信Guava有一个Table界面可以解决使用这种结构的痛苦,但我从未使用它。可能值得一试。

答案 2 :(得分:0)

你可以循环地图的入口集,并在密钥符合你的标准时总结值(在下面的代码中,我假设some_value是一个整数):

Map<MarketKey, Integer> map = getMap();
int sum = 0;
for (Map.Entry<MarketKey, Integer> entry : map.entrySet()) {
    if (entry.getKey().getX().equals(productId)) {
        sum += entry.getValue();
    }
}
System.out.println(sum);