/ java  

GeoHash的简单使用例子

以前开发一个项目有这样一个需求,货主找附件的车,原来是通过使经纬度进行匹配的,
因为经纬度是2个字段,所以匹配起来性能比较低,有一个geohash算法可以将二维的经纬度匹配
转为一维的匹配,降低查询效率.详细了解请参见相关博文

背景

网上百度的geohash java版的代码发现计算并不准确
于是去maven库查询了一下发现有对应的jar包,而且写的比较详细。
对应pom文件

<dependency>
<groupId>ch.hsr</groupId>
<artifactId>geohash</artifactId>
<version>1.0.10</version>
</dependency>

简单使用例子

 
import ch.hsr.geohash.GeoHash;
import com.lin.jedisFactory.JedisPoolUtil;
import redis.clients.jedis.Jedis;
import java.util.Set;
/**
* Created by Kevin on 2015/2/4.
*/
public class GeoHashTest {
public static void main(String[] args) {
/*假设货主的纬经度,南开区*/
double lat1 = 39.145609;
double lon1 = 117.154471;
/*假设司机1的纬经度,和平区*/
double lat2 = 39.122661;
double lon2 = 117.220299;
/*假设司机2的纬经度东丽*/
double lat3 = 39.093657;
double lon3 = 117.320047;
GeoHash geoHash1 = GeoHash.withCharacterPrecision(lat1,lon1,12);
GeoHash geoHash2 = GeoHash.withCharacterPrecision(lat2,lon2,12);
GeoHash geoHash3 = GeoHash.withCharacterPrecision(lat3,lon3,12);
System.out.println("南开区:"+geoHash1.toBase32());
System.out.println("和平区:"+geoHash2.toBase32());
System.out.println("东丽区:"+geoHash3.toBase32());
double distance1 = getDistance(lat1, lon1, lat2, lon2);
double distance2 = getDistance(lat1, lon1, lat3, lon3);
System.out.println("南开-和平 距离:" + distance1);
System.out.println("南开-东丽 距离:" + distance2);
String prefix = geoHash1.toBase32().substring(0,4);
System.out.println(prefix);
Jedis jedis = JedisPoolUtil.getJedis();
jedis.sadd(geoHash2.toBase32().substring(0,4), "siji1");
jedis.sadd(geoHash3.toBase32().substring(0,4), "siji2");
Set<String> ret = jedis.smembers(prefix);
JedisPoolUtil.release(jedis);
System.out.println(ret);
}
/**
* @param lat1 起始地纬度
* @param lon1 起始地经度
* @param lat2 目的地纬度
* @param lon2 目的地经度
* @return
*/
public static double getDistance(double lat1, double lon1, double lat2, double lon2) {
if (Math.abs(lat1) > 90 || Math.abs(lon1) > 180
|| Math.abs(lat2) > 90 || Math.abs(lon2) > 180) {
throw new IllegalArgumentException("The supplied coordinates are out of range.");
}
int R = 6378137;
double latRad1 = Math.toRadians(lat1);
double lonRad1 = Math.toRadians(lon1);
double latRad2 = Math.toRadians(lat2);
double lonRad2 = Math.toRadians(lon2);
//结果
double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((latRad1 - latRad2) / 2), 2)
+ Math.cos(latRad1) * Math.cos(latRad2) * Math.pow(Math.sin((lonRad1 - lonRad2) / 2), 2)))*R;
distance = Math.round(distance * 10000)/10000;
return Math.round(distance);
}
}


这里面给的GeoHash的构造方法时protected的,所以实例化不出来的,获取一个对象的方法对应的给了2种。
一个是withBitPrecision,里面的numberOfBits参数不好给,就是算出的那个二进制位数。
另一个是withCharacterPrecision,里面的numberOfCharacters就是给的字符串位数,最多12位,如果要取wwgqmsvc51ze对应的前四位,可以传值为4,我们用这个比较好。