解释
能否使用索引迭代哈希映射表?
不行。
HashMap
没有索引。根据底层实现的不同,这也是不可能的。Java 的 HashMap
并不一定由哈希表表示。它可以切换到红黑树,而且它们根本不提供直接访问。所以不行,是不可能的。
在这种方法中还存在另一个基本缺陷。 HashMap
不维护任何顺序。对其进行迭代会产生随机顺序,每次启动程序都可能会改变。但是,在这种方法中,您需要插入顺序。幸运的是,LinkedHashMap
可以实现此功能。但它仍然不能提供基于索引的访问。
解决方案
生成
但是,实际上您甚至不想要基于索引的访问。您想检索某个键范围,例如从 "BA"
到 "BM"
。与 HashMap
一起使用的一个好方法是生成您的键范围,并简单地使用 Map#get
检索数据:
char row = 'B';
char columnStart = 'A';
char columnEnd = 'M';
for (char column = columnStart; columnStart <= columnEnd; column++) {
String key = Chararcter.toString(row) + column;
String data = map.get(key);
...
}
如果需要适当处理边缘情况,例如环绕字母表(使用'A' + (column%alphabetSize)
),可能需要一些char
到int
的强制转换和加法的反向操作,没有测试。
NavigableMap
实际上有一种地图变体可提供您想要的大部分功能。但与简单的HashMap
相比,性能成本更高。这个接口称为NavigableMap
,而TreeMap
类是一个良好的实现。问题在于它需要明确的顺序。不过好消息是,您实际上希望使用String
的自然顺序,即词典顺序。
因此,您可以简单地将其与现有数据一起使用,然后使用NavigableMap#subMap
方法:
NavigableMap<String, String> map = new TreeMap<>(...);
String startKey = "BA";
String endKey = "BM";
Map<String, String> subMap = map.subMap(startKey, endKey);
for (Entry<String, String> entry : subMap.entrySet()) {
...
}
如果你需要多次执行这种类型的请求,这绝对是值得的,并且它是这种用例的完美数据结构。
链式迭代
如前所述,也可以(虽然不太高效)使用LinkedHashMap(以保持插入顺序),然后简单地迭代键范围。但是它有一些主要缺点,例如首先需要通过完全迭代到那里来定位范围的起始位置。并且它依赖于你正确插入它们的事实。
LinkedHashMap<String, String> map = ...
String startKey = "BA";
String endKey = "BM";
boolean isInRange = false;
for (Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
if (!isInRange) {
if (key.equals(startKey)) {
isInRange = true;
} else {
continue;
}
}
...
if (key.equals(endKey)) {
break;
}
}
BA
到BM
,然后使用map.get
简单地访问数据。 - ZabuzardNavigableMap
。 - chrylis -cautiouslyoptimistic-