Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make longitude and latitude as Key of HashMap in Java

Tags:

java

hashmap

I have data like this:

23.3445556 72.4535455 0.23434
23.3645556 72.4235455 0.53434
23.3245556 72.4635455 0.21434
23.3645556 72.2535455 0.25434

I want to make HashMap like this:

HashMap<23.34444,72.23455,0.2345566> demo = new HashMap()

Here 23.34444,72.23455 is a key and 0.2345566 is value.

This is because I want to traverse HashMap like this:

if(demo.latitude < 21.45454545 && demo.longitude > 72.3455)
    //get the value from hashMap   

long lat repn particular pixel on the map,each pixel have same value , i want to get avg value from particular area suppose x y and pixel will be upto 1 million

  • And i want to know does this is good way since daily it will get millions hit
like image 740
Gaurav Singh Avatar asked Jan 04 '23 21:01

Gaurav Singh


2 Answers

You could use the Point class to start off.

https://docs.oracle.com/javase/7/docs/api/java/awt/Point.html

int xE6 = x*1e6
int yE6 = y*1e6
new Point(xE6, yE6)

But since this is awt specific and a misuse of the class, you will probably eventually want to create your own.

public final class LatLon {
    private double lat;
    private double lon;

    public LatLon(double lat, double lon) {
        this.lat = lat;
        this.lon = lon;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        LatLon latLon = (LatLon) o;

        if (Double.compare(latLon.lat, lat) != 0) return false;
        return Double.compare(latLon.lon, lon) == 0;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = Double.doubleToLongBits(lat);
        result = (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(lon);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }

    public double getLat() {
        return lat;
    }

    public void setLat(double lat) {
        this.lat = lat;
    }

    public double getLon() {
        return lon;
    }

    public void setLon(double lon) {
        this.lon = lon;
    }
}

(autogenerated using IntelliJ)

This can be used like

public static void main(String[] args) {
    HashMap<LatLon, Double> demo = new HashMap<LatLon, Double>();
    demo.put(new LatLon(23.3445556,72.4535455), 0.23434);
    demo.put(new LatLon(23.3645556,72.4235455), 0.53434);
    demo.put(new LatLon(23.3245556,72.4635455), 0.21434);
    demo.put(new LatLon(23.3645556,72.2535455), 0.25434);
    System.out.println(demo.get(new LatLon(23.3645556,72.2535455))); //0.25434
}

The problem with using this class as is, is that it uses doubles. You want some sort of precision, given by the decimal location.

doubles have strange math, and can give you accuracy errors so I heartily recommend using a library designed for geo-coordinates.

Especially given

if(demo.latitude<21.45454545 && demo.longitude >72.3455)

This sort of check is best served by some sort of purpose built collection for dealing with bounds checks and co-ordinates if you end up hitting performance problems.

like image 139
Ryan Leach Avatar answered Jan 06 '23 10:01

Ryan Leach


I think you are approaching the problem the wrong way. Using a HashMap will not work correctly with greater than or lesser than comparisons. What would happen if you had 2 latlong keys that matched your comparison? What value do you choose?

I would probably solve your problem like this:

First, create a class that will contain both your "key" values and your "value" value

public class GeoValue {
  double lat;
  double lon;
  double value;
}

Then, add a comparison method to the class

public boolean lessThanLatGreaterThanLon(double lat, double lon) {
  return lat < this.lat && lon > this.lon;
}

Add all of those created objects to a Set type collection. If you use a HashSet, make sure that you also override .equals() and .hashCode methods for your GeoValue class.

To find the values you want you can use a filter method (if you're in Java8 or example)

final double lat = 3.5D;
final double lon = 4.5D;
Set<GeoValue> matchingValues = geoValues.stream()
    .filter(geo -> geo.lessThanLatGreaterThanLon(lat, lon))
    .collect(Collectors.toSet());

And you're ready to go.

like image 24
PentaKon Avatar answered Jan 06 '23 11:01

PentaKon