Range of values based on key values

I’m trying to implement a method of searching trough a large amount of 2D points for those that match a certain range. I’m thinking of creating HashMaps for <X, Point> and <Y, Point> but I’m wondering is HashMap good for doing this, because I will be taking points in a range, based on values from x_min to x_max and y_min to y_max.

So I will basically take all points from <X,Point> searching from x_min to x_max and compare them to points taken from <Y,Point> from y_min to y_max…

HashMap<Integer,Point> x_coordinates = new HashMap<Integer,Point>();
for(int i=x_min;i<=x_max;i++){
    if(x_coordinates.containsKey(i))
        x_coordinates.get(i);
}

HashMap<Integer,Point> y_coordinates = new HashMap<Integer,Point>();
for(int i=y_min;i<=y_max;i++){
    if(y_coordinates.containsKey(i))
         y_coordinates.get(i);
}

Is there a faster way to get a range of values from a HashMap, or some other type of data structure?

For example, if range = 200, select all points that match the range from x-200 to x+200 and from y-200 to y+200

I’m trying to avoid iteration through all of the points, but also I want to avoid making a huge 2D matrix, because the points in question are scattered around a large area.


After some testing and based on MichaelT’s answer, I’ve written this code:

TreeMap<Integer, TreeMap<Integer, Integer>> values;
for (int x : values.subMap(x_min, x_max).keySet()) {
        for (int y : values.get(x).subMap(y_min, y_max).values()) {
            // y here, represents the values of points in range...
        }
    }

2

What you are describing is a sparse matrix upon which you wish to do a range select.

I’m going to start out with no, neither a HashMap nor a LinkedHashMap will do what you want optimally. The reason for this to find the elements in a range HashMap is effectively walking an unordered list – O(n). The LinkedHashMap may be slightly more optimal than awful if the elements are put into the LinkedHashMap in sorted order and no new ones are added afterwards. Its still not an optimal approach because instead of O(n) you’re getting O(n/m) (because you stop walking the list once you get past the range) which is still effectively O(n). You can’t do a binary search on the LinkedHashMap list.

So, lets look at some other structures. What you are really after is the SortedMap interface. It allows you to quickly pull out the sub map from one key to another with SortedMap subMap(K fromKey, K toKey) which is what you want to do. Pick one of those classes and you will have what you are after.

You could then get the values for each of the submaps and do a boolean retainAll(Collection c) of one set to the other.

That’s the easy answer. It is effectively the lists of lists approach for the sparse matrix. You could, however encode the matrix instead in some other format that gives you a more direct sub range option. This isn’t something that is part of the Java standard library and you may find yourself going down this path for writing your own implementation in that case.

If you see the possibility in the future that this may be the case, you should consider writing your own interface for the sparse matrix and then implement a class behind it that does the lookups that you want. This way if you later decide that you need to change the implementation for some reason, its a matter of changing the implementation (a new class that wraps something else) rather than changing all the code to handle a different structure.

6

While your solution based on a treemap of treemaps will work, and is much better than the hashmap solution you started with, you may want to look into the possibility of using a QuadTree, which is a structure similar to a TreeMap but with a pair of coordinates as the key rather than just one. This makes selecting rectangular ranges from them particularly efficient. There are many implementations available for Java that can be found with a quick google.

1

You definitively should have a look at the k-d tree. This structure is typically used to answer questions such as “Does this point exist?”, “Where is the nearest post office?”, or “Who are the employees between 30 and 40 years old, and paid between 2K and 3K?”

So, your problem is a typical range search problem for which this structure is particularly well suited. According to Wikipedia, the worst case time for your problem, with this structure, is O(k.N^(1-(1/k)), where k is the number of dimensions (2, in your case) and N is the number of nodes in the tree.

Some limitations, however:

  • Building a k-d tree is time consuming, because you have to determine the “median” point in order get a balanced tree. That means that you have to order your points… You can decide to not use the median point as a basis for your splitting planes, but you could get an unbalanced tree, which will be less efficient. As a tradeoff, you can choose the median point among a subset of your point, to avoid a very bad selection.
  • If you have to add or to remove points, it can be done in log n time. But these operations are likely to unbalance the tree, so your performances will decrease over time, unless you spend extra time for re-balancing it. If you have to frequently add/remove points, and if your dimensions have fixed sizes, you could consider quadtrees as an alternative.

I have never used it, but apparently Java ML has a decent implementation of k-d trees.

Instead of two hash of coordinates, you may use a list of Point2D and iterate through it.
And extract a filtered List than you can
That way, only one loop is done.

    int distance = 200;
    Point2D.Double refPoint = new Point2D.Double(0,0);

    List<Point2D.Double> pointstoSearch = new ArrayList<Point2D.Double>();
    List<Point2D.Double> filtered = new ArrayList<Point2D.Double>();
    List<Point2D.Double> POIs = new ArrayList<Point2D.Double>();
    POIs.add(new Point2D.Double(99d,100d));
    POIs.add(new Point2D.Double(101.8, 202.3));        
    POIs.add(new Point2D.Double(-50, -98));      

    //filtering
    for (Point2D.Double point : POIs) {
       if (point.distance(refPoint)<= distance) filtered.add(point);
    }

    //now search only the matching points//filtering
    for (Point2D.Double poi : filtered) {
        for (Point2D.Double point : pointstoSearch) {
            if (poi.equals(point)) //match
        }
    }

For maximum efficiency, and if the map of searched coordinates (POI in my sample) is ~constant, you should consider using a quadtree structure.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Range of values based on key values

I’m trying to implement a method of searching trough a large amount of 2D points for those that match a certain range. I’m thinking of creating HashMaps for <X, Point> and <Y, Point> but I’m wondering is HashMap good for doing this, because I will be taking points in a range, based on values from x_min to x_max and y_min to y_max.

So I will basically take all points from <X,Point> searching from x_min to x_max and compare them to points taken from <Y,Point> from y_min to y_max…

HashMap<Integer,Point> x_coordinates = new HashMap<Integer,Point>();
for(int i=x_min;i<=x_max;i++){
    if(x_coordinates.containsKey(i))
        x_coordinates.get(i);
}

HashMap<Integer,Point> y_coordinates = new HashMap<Integer,Point>();
for(int i=y_min;i<=y_max;i++){
    if(y_coordinates.containsKey(i))
         y_coordinates.get(i);
}

Is there a faster way to get a range of values from a HashMap, or some other type of data structure?

For example, if range = 200, select all points that match the range from x-200 to x+200 and from y-200 to y+200

I’m trying to avoid iteration through all of the points, but also I want to avoid making a huge 2D matrix, because the points in question are scattered around a large area.


After some testing and based on MichaelT’s answer, I’ve written this code:

TreeMap<Integer, TreeMap<Integer, Integer>> values;
for (int x : values.subMap(x_min, x_max).keySet()) {
        for (int y : values.get(x).subMap(y_min, y_max).values()) {
            // y here, represents the values of points in range...
        }
    }

2

What you are describing is a sparse matrix upon which you wish to do a range select.

I’m going to start out with no, neither a HashMap nor a LinkedHashMap will do what you want optimally. The reason for this to find the elements in a range HashMap is effectively walking an unordered list – O(n). The LinkedHashMap may be slightly more optimal than awful if the elements are put into the LinkedHashMap in sorted order and no new ones are added afterwards. Its still not an optimal approach because instead of O(n) you’re getting O(n/m) (because you stop walking the list once you get past the range) which is still effectively O(n). You can’t do a binary search on the LinkedHashMap list.

So, lets look at some other structures. What you are really after is the SortedMap interface. It allows you to quickly pull out the sub map from one key to another with SortedMap subMap(K fromKey, K toKey) which is what you want to do. Pick one of those classes and you will have what you are after.

You could then get the values for each of the submaps and do a boolean retainAll(Collection c) of one set to the other.

That’s the easy answer. It is effectively the lists of lists approach for the sparse matrix. You could, however encode the matrix instead in some other format that gives you a more direct sub range option. This isn’t something that is part of the Java standard library and you may find yourself going down this path for writing your own implementation in that case.

If you see the possibility in the future that this may be the case, you should consider writing your own interface for the sparse matrix and then implement a class behind it that does the lookups that you want. This way if you later decide that you need to change the implementation for some reason, its a matter of changing the implementation (a new class that wraps something else) rather than changing all the code to handle a different structure.

6

While your solution based on a treemap of treemaps will work, and is much better than the hashmap solution you started with, you may want to look into the possibility of using a QuadTree, which is a structure similar to a TreeMap but with a pair of coordinates as the key rather than just one. This makes selecting rectangular ranges from them particularly efficient. There are many implementations available for Java that can be found with a quick google.

1

You definitively should have a look at the k-d tree. This structure is typically used to answer questions such as “Does this point exist?”, “Where is the nearest post office?”, or “Who are the employees between 30 and 40 years old, and paid between 2K and 3K?”

So, your problem is a typical range search problem for which this structure is particularly well suited. According to Wikipedia, the worst case time for your problem, with this structure, is O(k.N^(1-(1/k)), where k is the number of dimensions (2, in your case) and N is the number of nodes in the tree.

Some limitations, however:

  • Building a k-d tree is time consuming, because you have to determine the “median” point in order get a balanced tree. That means that you have to order your points… You can decide to not use the median point as a basis for your splitting planes, but you could get an unbalanced tree, which will be less efficient. As a tradeoff, you can choose the median point among a subset of your point, to avoid a very bad selection.
  • If you have to add or to remove points, it can be done in log n time. But these operations are likely to unbalance the tree, so your performances will decrease over time, unless you spend extra time for re-balancing it. If you have to frequently add/remove points, and if your dimensions have fixed sizes, you could consider quadtrees as an alternative.

I have never used it, but apparently Java ML has a decent implementation of k-d trees.

Instead of two hash of coordinates, you may use a list of Point2D and iterate through it.
And extract a filtered List than you can
That way, only one loop is done.

    int distance = 200;
    Point2D.Double refPoint = new Point2D.Double(0,0);

    List<Point2D.Double> pointstoSearch = new ArrayList<Point2D.Double>();
    List<Point2D.Double> filtered = new ArrayList<Point2D.Double>();
    List<Point2D.Double> POIs = new ArrayList<Point2D.Double>();
    POIs.add(new Point2D.Double(99d,100d));
    POIs.add(new Point2D.Double(101.8, 202.3));        
    POIs.add(new Point2D.Double(-50, -98));      

    //filtering
    for (Point2D.Double point : POIs) {
       if (point.distance(refPoint)<= distance) filtered.add(point);
    }

    //now search only the matching points//filtering
    for (Point2D.Double poi : filtered) {
        for (Point2D.Double point : pointstoSearch) {
            if (poi.equals(point)) //match
        }
    }

For maximum efficiency, and if the map of searched coordinates (POI in my sample) is ~constant, you should consider using a quadtree structure.

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật