Java 高效地迭代hashmap中所有匹配的键?
我有一个Java 高效地迭代hashmap中所有匹配的键?,java,search,performance,iterator,hashmap,Java,Search,Performance,Iterator,Hashmap,我有一个HashMap,有数百万条条目 需要检索其键与一组特定条件匹配的所有项(在本例中,每个键是一个具有两个整数属性的对象;我需要检索每个整数都在指定范围内的所有键) 迭代所有这些键的最快、最有效的方法是什么 更新: 在这种特殊情况下,虽然我没有预先指定,但键中的第一个整数自然优先于第二个整数。可能没有比以下内容更快的解决方案: for (final KeyObj key : map.keySet()) { // do work } 如果由于某种原因a无法工作,则迭代的标准方法是使用
HashMap
,有数百万条条目
需要检索其键与一组特定条件匹配的所有项(在本例中,每个键是一个具有两个整数属性的对象;我需要检索每个整数都在指定范围内的所有键)
迭代所有这些键的最快、最有效的方法是什么
更新:
在这种特殊情况下,虽然我没有预先指定,但键中的第一个整数自然优先于第二个整数。可能没有比以下内容更快的解决方案:
for (final KeyObj key : map.keySet()) {
// do work
}
如果由于某种原因a无法工作,则迭代的标准方法是使用条目集
for (Map.Entry<MyKeyType, MyValueType> entry : myMap.entrySet()) {
MyKeyType key = entry.getKey();
if (isValid(key)) {
// do whatever
validList.add(entry.getValue());
}
}
for(Map.Entry:myMap.entrySet()){
MyKeyType key=entry.getKey();
如果(isValid(key)){
//做任何事
add(entry.getValue());
}
}
这样,您就不必为有效密钥执行额外的
myMap.get(key)
调用。如果不遍历整个密钥集,则无法执行此操作
如果您确定没有其他条目具有与这些整数属性相同的值,则可以使用具有排序条件的树映射,该树映射将按两个整数属性的某种组合进行排序,然后您可以直接找到第一个匹配项,然后从那里迭代到第一个不匹配项。但你似乎不太可能达到这些条件
因为集合有相当低的开销(所有都是通过引用存储的),我会考虑做两个排序的集合,可能是树集,一个是由第一个属性排序的,另一个是由第二个属性排序的。然后从两个集合中挑选出符合条件的所有值,并将它们合并在一起。
哈希映射不是查找位于某个范围内的键的有效数据结构。通常,在散列映射中可以有效找到的唯一键是具有与您所拥有的相同散列的键(即相等的键) 要查找位于某个范围内的键,最好使用某种类型的键,例如树形图,然后可以使用SortedMap.subMap(low,high)视图方法查看树形图至于根据两个键找到一个键,那就更难了。最好的方法可能是迭代第一个整数范围的子映射,然后检查第二个整数是否在指定范围内。这至少将扫描限制为具有范围内一个整数的键。尝试根据整数对地图进行排序,该整数在可能需要搜索的范围内具有更自然的值分布 >你可能想考虑某种类型的SQL数据库,可能是内存中的一个。这在很大程度上取决于它的重要性以及它的快速性。然后您可以在SQL中执行此操作,并让引擎执行所有优化工作。下面是一个解决方案,使用:
publicstaticvoidmain(字符串[]args){
比较器fooparator=新比较器(){
@凌驾
公共整数比较(Foo o1,Foo o2){
返回o1。与(o2)相比;
}
};
树映射=新树映射(fooComparator);
地图放置(新富(1,4)),;
地图放置(新富(1,3)),;
新富(二,四),"地图",;
新富(3,4),"地图",;
地图.拼图(新富(8,10));;
地图.put(新富(8,17));;
地图.拼图(新富(10,10));;
INTA=2;
int b=5;
for(Foo f:getKeysInRange(map,a,b)){
系统输出打印ln(f);
}
}
公共静态列表getKeysInRange(树映射,整型低,整型高){
Foo-key1=新的Foo(低,低);
Foo键2=新的Foo(高,高);
Foo fromKey=map.ceilingKey(键1);
Foo-toKey=map.floorKey(键2);
if(fromKey!=null&&toKey!=null&&fromKey.compareTo(toKey)<0)
返回新的ArrayList(map.subMap(fromKey,true,toKey,true).keySet());
返回新的ArrayList();
}
公共静态类Foo实现了可比较的{
私人互联网i;
私人int j;
私人Foo(inti,intj){
超级();
这个。i=i;
这个。j=j;
}
公共int min(){
if(ij)
返回i;
其他的
返回j;
}
@凌驾
公共字符串toString(){
返回“I=“+I+”J=“+J;
}
@凌驾
公共国际比较(Foo o){
如果(this.min()>o.min()){
返回1;
}else if(this.min()o.max())
返回1;
else if(this.max()布鲁诺·康德提供的解决方案是一个良好的开端。然而,我阅读原始问题的方式是,key对象包含两个整数,问题是关于检索所有键/值对的最快方式,这些键/值对匹配第一个整数的一个范围,匹配第二个整数的第二个范围。bruno解决方案假设键具有自然顺序,其中第一个整数始终优先于第二个整数。它还假设只有一个范围
对于这个更一般的情况,我想:
使用支持整数1的比较器将键/值插入树映射
使用支持整数2的比较器将相同的键/值插入第二个树形图
然后,可以在每个树映射上使用subMap(),并使用范围来获得底层树映射的有序视图。然后,您可以基于这些子贴图的键集()的交集(retainAll())创建一个新的结果树集。@DanM请使用树更新查看我的解决方案,并根据您将要检索的可能值,使用in函数对贴图进行排序可能更有效
public static void main(String[] args) {
Comparator<Foo> fooComparator = new Comparator<Foo>() {
@Override
public int compare(Foo o1, Foo o2) {
return o1.compareTo(o2);
}
};
TreeMap<Foo, String> map = new TreeMap<Foo, String>(fooComparator);
map.put(new Foo(1, 4), "");
map.put(new Foo(1, 3), "");
map.put(new Foo(2, 4), "");
map.put(new Foo(3, 4), "");
map.put(new Foo(8, 10), "");
map.put(new Foo(8, 17), "");
map.put(new Foo(10, 10), "");
int a = 2;
int b = 5;
for (Foo f : getKeysInRange(map, a, b)) {
System.out.println(f);
}
}
public static List<Foo> getKeysInRange(TreeMap<Foo, String> map, int low, int high) {
Foo key1 = new Foo(low, low);
Foo key2 = new Foo(high, high);
Foo fromKey = map.ceilingKey(key1);
Foo toKey = map.floorKey(key2);
if (fromKey != null && toKey != null && fromKey.compareTo(toKey) < 0)
return new ArrayList<Foo>(map.subMap(fromKey, true, toKey, true).keySet());
return new ArrayList<Foo>();
}
public static class Foo implements Comparable<Foo> {
private int i;
private int j;
private Foo(int i, int j) {
super();
this.i = i;
this.j = j;
}
public int min() {
if (i < j)
return i;
else
return j;
}
public int max() {
if (i > j)
return i;
else
return j;
}
@Override
public String toString() {
return "I=" + i + "J=" + j;
}
@Override
public int compareTo(Foo o) {
if (this.min() > o.min()) {
return 1;
} else if (this.min() < o.min())
return -1;
else {
if (this.max() > o.max())
return 1;
else if (this.max() < o.max())
return -1;
else
return 0;
}
}
}