我正在搜索各种主题,但没有找到任何适合我的情况的解决方案。
我们假设我需要存储以下值: (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 必须具有唯一的值,而在我的示例中,情况并非如此。
答案 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)
)的效率会低于HashMap
或HashMap
HashMap
的效果。 (O(1))
。这是SortedMap
的排序性质的必然结果,而不是取决于其特定的实现。
迭代具有给定产品ID的所有项目的行为规模如何进行分析是非常棘手的,部分取决于segment_id
每product_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);