代码之家  ›  专栏  ›  技术社区  ›  DanM

高效地迭代hashmap中所有匹配的键?

  •  4
  • DanM  · 技术社区  · 17 年前

    我有一个 HashMap 数以百万计的条目。

    需要检索其键与一组特定条件匹配的所有项(在本例中,每个键是一个具有两个整数属性的对象;我需要检索每个整数都在指定范围内的所有键)。

    迭代所有这些键的最快、最有效的方法是什么?

    更新: 在这个特殊的例子中,虽然我没有预先指定,但键中的第一个整数自然优先于第二个整数。

    7 回复  |  直到 17 年前
        1
  •  7
  •   Avi    17 年前

    要查找位于特定范围内的关键点,最好使用 SortedMap 某种类型的,例如树状图,然后可以使用SortedMap.subMap(低、高)视图方法查看树状图。

    至于根据

        2
  •  3
  •   bruno conde    17 年前

    这里有一个 使用 TreeMap :

    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;
            }
        }
    }
    
        3
  •  1
  •   Paul Tomblin    17 年前

    如果您确定没有其他条目具有与这些整数属性相同的值,则可以使用具有排序条件的树映射,该树映射将按两个整数属性的某种组合进行排序,然后您可以直接找到第一个匹配项,然后从那里迭代到第一个不匹配项。但你似乎不太可能达到这些条件。

    因为集合有很低的开销(所有都是通过引用存储的),所以我会考虑两个排序的集合,可能是树集,一个是由第一个属性排序的,另一个是由第二个属性排序的,然后从集合中挑选出符合标准的所有值并将它们结合在一起。

        4
  •  1
  •   Gary    17 年前

    bruno conde提供的解决方案是一个良好的开端。然而,我阅读原始问题的方式是,key对象包含两个整数,问题是关于检索所有键/值对的最快方式,这些键/值对匹配第一个整数的一个范围,匹配第二个整数的第二个范围。bruno解决方案假设键具有自然顺序,其中第一个整数始终优先于第二个整数。它还假设只有一个范围。

    对于这个更一般的情况,我想: 使用支持整数1的比较器将键/值插入树映射

        5
  •  0
  •   Hank Gay    17 年前

    for (final KeyObj key : map.keySet()) {
        // do work
    }
    
        6
  •  0
  •   Michael Myers KitsuneYMG    17 年前

    TreeSet 由于某种原因无法工作,迭代的标准方法是使用条目集。

    for (Map.Entry<MyKeyType, MyValueType> entry : myMap.entrySet()) {
        MyKeyType key = entry.getKey();
        if (isValid(key)) {
            // do whatever
            validList.add(entry.getValue());
        }
    }
    

    这样,你就不必做额外的事情了 myMap.get(key) 调用有效密钥。

        7
  •  0
  •   sblundy    17 年前

    Derby H2 . 这在很大程度上取决于它的重要性以及它的快速性。然后可以在SQL中执行此操作,并让引擎完成所有优化工作。

    推荐文章