java 身边距离怎么查询_附近的人位置距离计算方法

2023-11-14

附近的人的位置用经纬度表示,然后通过两点的经纬度计算距离。根据网上的推荐,最终采用geohash。

geohash的实现java版:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 importjava.util.BitSet;2 importjava.util.HashMap;3 importjava.util.Map;4

5 importorg.apache.commons.lang3.StringUtils;6

7 public classGeohash {8

9 private static int numbits = 6 * 5;10 final static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8',11 '9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p',12 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};13

14 final static HashMap lookup = new HashMap();15 static{16 int i = 0;17 for (charc : digits)18 lookup.put(c, i++);19

20 }21

22 publicGeohash() {23 setMap();24 }25

26 public double[] decode(String geohash) {27 StringBuilder buffer = newStringBuilder();28 for (charc : geohash.toCharArray()) {29

30 int i = lookup.get(c) + 32;31 buffer.append(Integer.toString(i, 2).substring(1));32 }33

34 BitSet lonset = newBitSet();35 BitSet latset = newBitSet();36

37 //even bits

38 int j = 0;39 for (int i = 0; i < numbits * 2; i += 2) {40 boolean isSet = false;41 if (i

46 //odd bits

47 j = 0;48 for (int i = 1; i < numbits * 2; i += 2) {49 boolean isSet = false;50 if (i

55 double lon = decode(lonset, -180, 180);56 double lat = decode(latset, -90, 90);57

58 return new double[] { lat, lon };59 }60

61 private double decode(BitSet bs, double floor, doubleceiling) {62 double mid = 0;63 for (int i = 0; i < bs.length(); i++) {64 mid = (floor + ceiling) / 2;65 if(bs.get(i))66 floor =mid;67 else

68 ceiling =mid;69 }70 returnmid;71 }72

73 publicString encode(String lat, String lon) {74

75 returnencode(Double.parseDouble(lat), Double.parseDouble(lon));76

77 }78

79 public String encode(double lat, doublelon) {80 BitSet latbits = getBits(lat, -90, 90);81 BitSet lonbits = getBits(lon, -180, 180);82 StringBuilder buffer = newStringBuilder();83 for (int i = 0; i < numbits; i++) {84 buffer.append((lonbits.get(i)) ? '1' : '0');85 buffer.append((latbits.get(i)) ? '1' : '0');86 }87 return base32(Long.parseLong(buffer.toString(), 2));88 }89

90 private BitSet getBits(double lat, double floor, doubleceiling) {91 BitSet buffer = newBitSet(numbits);92 for (int i = 0; i < numbits; i++) {93 double mid = (floor + ceiling) / 2;94 if (lat >=mid) {95 buffer.set(i);96 floor =mid;97 } else{98 ceiling =mid;99 }100 }101 returnbuffer;102 }103

104 public static String base32(longi) {105 char[] buf = new char[65];106 int charPos = 64;107 boolean negative = (i < 0);108 if (!negative)109 i = -i;110 while (i <= -32) {111 buf[charPos--] = digits[(int) (-(i % 32))];112 i /= 32;113 }114 buf[charPos] = digits[(int) (-i)];115

116 if(negative)117 buf[--charPos] = '-';118 return new String(buf, charPos, (65 -charPos));119 }120

121 /*********************** 获取九个的矩形编码 ****************************************/

122 public static String BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz";123 public static Map BORDERS = new HashMap();124 public static Map NEIGHBORS = new HashMap();125

126 public static voidsetMap() {127 NEIGHBORS.put("right:even", "bc01fg45238967deuvhjyznpkmstqrwx");128 NEIGHBORS.put("left:even", "238967debc01fg45kmstqrwxuvhjyznp");129 NEIGHBORS.put("top:even", "p0r21436x8zb9dcf5h7kjnmqesgutwvy");130 NEIGHBORS.put("bottom:even", "14365h7k9dcfesgujnmqp0r2twvyx8zb");131

132 NEIGHBORS.put("right:odd", "p0r21436x8zb9dcf5h7kjnmqesgutwvy");133 NEIGHBORS.put("left:odd", "14365h7k9dcfesgujnmqp0r2twvyx8zb");134 NEIGHBORS.put("top:odd", "bc01fg45238967deuvhjyznpkmstqrwx");135 NEIGHBORS.put("bottom:odd", "238967debc01fg45kmstqrwxuvhjyznp");136

137 BORDERS.put("right:even", "bcfguvyz");138 BORDERS.put("left:even", "0145hjnp");139 BORDERS.put("top:even", "prxz");140 BORDERS.put("bottom:even", "028b");141

142 BORDERS.put("right:odd", "prxz");143 BORDERS.put("left:odd", "028b");144 BORDERS.put("top:odd", "bcfguvyz");145 BORDERS.put("bottom:odd", "0145hjnp");146

147 }148

149 /**

150 * 获取九个点的矩形编码151 *152 *@paramgeohash153 *@return

154 */

155 publicString[] getGeoHashExpand(String geohash) {156 try{157 String geohashTop = calculateAdjacent(geohash, "top");158 String geohashBottom = calculateAdjacent(geohash, "bottom");159 String geohashRight = calculateAdjacent(geohash, "right");160 String geohashLeft = calculateAdjacent(geohash, "left");161 String geohashTopLeft = calculateAdjacent(geohashLeft, "top");162 String geohashTopRight = calculateAdjacent(geohashRight, "top");163 String geohashBottomRight =calculateAdjacent(geohashRight,164 "bottom");165 String geohashBottomLeft = calculateAdjacent(geohashLeft, "bottom");166 String[] expand ={ geohash, geohashTop, geohashBottom,167 geohashRight, geohashLeft, geohashTopLeft, geohashTopRight,168 geohashBottomRight, geohashBottomLeft };169 returnexpand;170 } catch(Exception e) {171 return null;172 }173 }174

175 /**

176 * 分别计算每个点的矩形编码177 *178 *@paramsrcHash179 *@paramdir180 *@return

181 */

182 public staticString calculateAdjacent(String srcHash, String dir) {183 srcHash =srcHash.toLowerCase();184 char lastChr = srcHash.charAt(srcHash.length() - 1);185 int a = srcHash.length() % 2;186 String type = (a > 0) ? "odd" : "even";187 String base = srcHash.substring(0, srcHash.length() - 1);188 if (BORDERS.get(dir + ":" + type).indexOf(lastChr) != -1) {189 base =calculateAdjacent(base, dir);190 }191 base =base192 + BASE32.toCharArray()[(NEIGHBORS.get(dir + ":" +type)193 .indexOf(lastChr))];194 returnbase;195 }196

197 //@Deprecated198 //public static void expandLngLat(String geohash, int len){199 //boolean is_even = true;200 //double[] lat = new double[3];201 //double[] lon = new double[3];202 //lat[0] = -90.0;203 //lat[1] = 90.0;204 //lon[0] = -180.0;205 //lon[1] = 180.0;206 //double lat_err = 90.0;207 //double lon_err = 180.0;208 //char[] geohashChar = geohash.toCharArray();209 // //String[] BITS = {"16", "8", "4", "2", "1"};210 //int[] BITS = {16, 8, 4, 2, 1};211 //for (int i = 0; i < geohashChar.length; i++) {212 //char c = geohashChar[i];213 //int cd = BASE32.indexOf(c);214 //for (int j = 0; j < 5; j++) {215 //int mask = BITS[j];216 //if (is_even) {217 //lon_err /= 2;218 //refine_interval(lon, cd, mask);219 //} else {220 //lat_err /= 2;221 //refine_interval(lat, cd, mask);222 //}223 //is_even = !is_even;224 //}225 //}226 //lat[2] = (lat[0] + lat[1])/2;227 // //1:[38.8970947265625, 38.902587890625, 38.89984130859375]228 // //1: 38.8970947265625, 38.902587890625, 38.89984130859375229 // //2:[38.902587890625, 38.9080810546875, 38.90533447265625]230 // //2: 38.902587890625, 38.9080810546875, 38.90533447265625231 //lon[2] = (lon[0] + lon[1])/2;232 // //1:[-77.047119140625, -77.0361328125, -77.0416259765625]233 // //1: -77.047119140625, -77.0361328125, -77.0416259765625234 // //2:[-77.047119140625, -77.0361328125, -77.0416259765625]235 // //2: -77.047119140625, -77.0361328125, -77.0416259765625236 //

237 //String topLeft = lat[0]+","+lon[0];238 //String topRight = lat[0]+","+lon[1];239 //

240 //String bottomleft = lat[1]+","+lon[0];241 //String bottoomRight = lat[1]+","+lon[1];242 //String centerPoint = (lat[0]+lat[1])/2+","+(lon[0]+lon[1])/2;243 //

244 //String centerTop = lat[0]+","+(lon[0]+lon[1])/2;245 //String centerBottom = lat[1]+","+(lon[0]+lon[1])/2;246 //

247 //String centerLeft = (lat[0]+lat[1])/2+","+lon[0];248 //String centerRight = (lat[0]+lat[1])/2+","+lon[1];249 // //System.out.println("topLeft:["+topLeft+"] geoHash:"+g.encode(lat[0],250 //lon[0]));251 // //System.out.println("topRight:["+topRight+"] geoHash:"+g.encode(lat[0],252 //lon[1]));253 // //

254 //System.out.println("bottomleft:["+bottomleft+"] geoHash:"+g.encode(lat[1],255 //lon[0]));256 // //

257 //System.out.println("bottoomRight:["+bottoomRight+"] geoHash:"+g.encode(lat[1],258 //lon[1]));259 // //

260 //System.out.println("centerPoint:["+centerPoint+"] geoHash:"+g.encode((lat[0]+lat[1])/2,261 //(lon[0]+lon[1])/2));262 // //

263 //System.out.println("centerTop:["+centerTop+"] geoHash:"+g.encode(lat[0],264 //(lon[0]+lon[1])/2));265 // //

266 //System.out.println("centerBottom:["+centerBottom+"] geoHash:"+g.encode(lat[1],267 //(lon[0]+lon[1])/2));268 // //

269 //System.out.println("centerLeft:["+centerLeft+"] geoHash:"+g.encode((lat[0]+lat[1])/2,270 //lon[0]));271 // //

272 //System.out.println("centerRight:["+centerRight+"] geoHash:"+g.encode((lat[0]+lat[1])/2,273 //lon[1]));274 //

275 //}276 //

277 //@Deprecated278 //public static void refine_interval(double[] interval, int cd, int mask){279 //if ((cd & mask)>0){280 //interval[0] = (interval[0] + interval[1])/2;281 //}else{282 //interval[1] = (interval[0] + interval[1])/2;283 //}284 //}285 //

286

287 //****************************************************************************************************************

288

289 private static final double EARTH_RADIUS = 6371;//赤道半径(单位m)

290

291 /**

292 * 转化为弧度(rad)293 **/

294 private static double rad(doubled) {295 return d * Math.PI / 180.0;296 }297

298 /**

299 * 基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多,相差范围在0.2米以下300 *301 *@paramlon1302 * 第一点的精度303 *@paramlat1304 * 第一点的纬度305 *@paramlon2306 * 第二点的精度307 *@paramlat2308 * 第二点的纬度309 *@return返回的距离,单位m310 **/

311 public double getDistance(double lon1, double lat1, doublelon2,312 doublelat2) {313 double radLat1 =rad(lat1);314 double radLat2 =rad(lat2);315 double a = radLat1 -radLat2;316 double b = rad(lon1) -rad(lon2);317 double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)318 + Math.cos(radLat1) *Math.cos(radLat2)319 * Math.pow(Math.sin(b / 2), 2)));320 s = s *EARTH_RADIUS;321 s = Math.round(s * 1000)/1000.0;322 returns;323 }324

325 /*

326 * 永相逢超市 108.83457500177 34.256981052624 wqj6us6cmkj5bbfj6qdg s6q08ubhhuq7327 */

328 public static void main(String[] args) throwsException {329

330 //东四站 灯市口站

331 double lon1 = 116.4174628300;332 double lat1 = 39.9243669400;333 double lon2 = 116.4177739600;334 double lat2 = 39.9171260300;335 doubledist;336 String geocode;337

338 Geohash geohash = newGeohash();339 dist =geohash.getDistance(lon1, lat1, lon2, lat2);340 System.out.println("两点相距:" + dist + " km");341

342 geocode =geohash.encode(lat1, lon1);343 System.out.println("当前位置编码:" +geocode);344 double[] decode = newGeohash().decode(geocode);345 for (doubled : decode) {346 System.out.println(d);347 }348

349 geocode =geohash.encode(lat2, lon2);350 System.out.println("远方位置编码:" +geocode);351 decode = newGeohash().decode(geocode);352 for (doubled : decode) {353 System.out.println(d);354 }355

356 /*获取的geohash多少位,位数越长,精度越准*/

357 int geohashLen = 5;358

359 /*获取中心点的geohash*/

360 String code = geohash.encode(lat1, lon1).substring(0, geohashLen);361

362 /*获取所有的矩形geohash, 一共是九个 ,包含中心点,打印顺序请参考图2*/

363 String[] result =geohash.getGeoHashExpand(code);364 for(String string : result) {365 System.out.println(string);366 }367

368 }369

370 }

View Code

原理看起来很容易懂的样子,就是分区编码。但仔细一想却不是那么简单。算法设计,编码设计,为什么相似等等,现在只会痛恨当时为啥不好好学数学。

那么,只要在上传位置信息的时候计算geohash,然后根据geohash的精度前缀进行匹配查询就可以搜索附近的人。但有两个问题。

问题1:

计算的附近的概念不精准,仅仅只是一个区域,在边界问题上需要考虑。距离相近的在边界位置geohash显示却在两块区域。因此引入周围8个区域来精算中间一个区域的位置。这样做会把中间区域周围的包含,但最大范围无法估量。因为周围8块所代表的的精度算法,仅仅是该区域内的,而不是包含所有。就是说,假如中间区域精度1km以内,我需要将周围的区域加上才能把全部1km以内的位置包含。如下图所示:

3777ccacf926e1907d496e07c2ea6fe7.png

2387155fa46a3b8d7949e18738356443.png

我按照0110的编码匹配,只能得到红色区域内的位置。倘若客户站在区域中心,那么正好该区域的精度就是距离客户的最大距离。但是,在其他区域的客户,比如红点。记红点为A点,A点距离最近的除了0110还包括另外三个区域的点。这样,若仅仅只按中心区域0110搜索附近的人反而不是正确的。于是引入周围8个区域的点。这样,可以把0110区域的人的附近的点全部包含。

距离:

记一个geohash的精度(区域的边长)为len,记最大距离为可以搜索到的最远的附近的位置,记最小距离为该距离内的所有位置必然包含在内。比如最小距离为d,则方圆为d的距离内的所有点都包含。

位于中心区域0110的人最大附近距离为:两个对角线b=2√2len。最小距离为:a=len

再次重申:可以肯定搜索到一个精度内的所有人,但还可以包含附近大于一个精度达部分人。

问题2:

距离需要进行2次计算。若有排序概念还需要排序。

我的抉择:

我选择了匹配前6位,测试距离大概1km以内。然后面临另一个问题:分页。

分页:

客户端滚动加载,我一次查完9个区域内所有点,然后根据时间排序。选取该时间之前的n条记录。第一页就是前n条。第一页最后一条的时间为t1,第二页就是t1时间往前的的n条,以此类推。那么,问题来了。假如第一页花费时间t,在这段时间内,本来第二页的数据位置信息更新(每次更新后时间改变);然后查询第二页的时候,变动的数据不包含在内了。也就是说,遗漏了变化的点。

在我看来,位置信息可以延时,但不要遗漏。因为喜欢查看附近的人的位置通常是实时改变的,而我们遗漏的恰恰就是互相有需求的双方。所以,要一次查询一个很大范围内的数据。

办法:

我一次将9个区域的点全部取出,然后缓存。由于geohash区域内的人共享一个查询,因此将geohash的前缀作为key来缓存该区域附近的点。那么,其他该区域的人也可以使用本次查询的结果。

用java做分页处理。

第一次请求,所有数据缓存。然后取出前n个,如果排序,则排序后的前n个。缓存信息不可以改变。第二次请求,计算缓存的索引n开始的n个。....

缺点:

我需要每次都计算距离,排序。

思考:

我想要第一次计算完之后缓存数据,然后第二次直接取出想要的部分。进而省略每次的计算。接着,问题来了。

第一次数据库的查询数据缓存,标记为key_all;客户a通过缓存计算距离,排序,放入缓存,标记为key_a;显然,两个缓存有大量的重复数据。如果仅仅是标记索引,那计算结果的部分无法保存,所以需要复制而后修改,而后存储。虽然省略了部分计算,但加大了内存需求。

对于时间和空间的问题,我们再来看需求。需求是附近的人,而我查看附近的人的翻页频率并不高,也就是说每次计算的次数很少。那我可以不用为了减少部分计算而加大存储。因为加大存储需要空间加倍,而减少计算影响不大。所以放弃每人都缓存数据。采用每次翻页时计算需要的数据。

然后,面临两个问题。

第一个:ehcache读取后的数据,被计算修改后缓存相应改变,因为对象引用相同。

然后我花了两天看反射和序列化,最后采用序列化来复制缓存对象。成功后又觉得不对,缓存显然是有序列化的,我干嘛重复加工,找到配置,copyOnRead="true" copyOnWrite="true"。解决。

第二个:排序和分页的计算方法。

客户分页的时候也会传新的位置过来,位置必然发生改变。那么按照上次分页计算的距离就不能使用了。

也就是说,我需要用户只传递一次位置,只在第一页请求的时候传递位置,往后的页码忽略其位置。因此,还需要保存第一次请求的位置。首先我要区分第一次和其他。根据现有标记无法区分,因为是按照时间排序的。所以不能区分,也就不能忽略。也就是,用户每次请求传递位置和时间。查询该位置附近该时间之前的n条记录。

finally:缓存边界

缓存是有时间限制的,如果用户第一页查询完后,第二页缓存更新,第二页就不能和第一页衔接了。

所以,为了逻辑上还是拓扑上啥的,严谨不漏。我不能接着查询第二页了。也就是读取缓存的时候,策略需要改变。若缓存不在,重新缓存数据,并查询第一页,告诉客户端刷新页面而不是请求第二页。缺点是若用户第二页是缓存结束前访问的就只能刷新,用户体验不好。所以还是不提示了?我不是产品,但严谨的态度来说,我悄悄更新?也就是第二页数据若缓存不在,我就接着查询缓存第一页作为第二页给客户端。又想多了,我不是根据页码分页的,而是根据时间分页的。那么缓存更新的时候需不需要限制时间呢。我需要按时间排序,而且需要全部数据缓存。所以不能限制时间。这样,取出新缓存的数据中,前n条,忽视时间。当缓存存在而不更新的时候才按照时间取下一组数据。客户端虽然会发现和第一页一样的数据,但时间不一样了。为了避免缓存边界的发生,我或许应该延长缓存时间。

算法遗漏:

假设默认第一次搜索是geohash匹配前6位,1km以内。设计一共2页,翻到第三页的时候就要加载更大范围内的。所以匹配前5位,这样,问题出现了。

重新匹配前5位的时候包含了之前查过的前6位的数据。

我当然可以对比数组,取消已经显示的,或者在查询匹配的时候就直接去除(比如java 8中的stream)。但这样查询语句就变的复杂。比如我的坐标是&lat=39.9346650000&lon=116.3951690000,对应的geohash是:wx4g0tukk10e。第一次匹配前6位的sql:

1 SELECT id, lat, lon, geohash, updatetime FROMuser_location2 WHERE 1=1

3 and(4 geohash like 'wx4g0t%' or geohash like 'wx4g0w%' or geohash like 'wx4g0s%'

5 or geohash like 'wx4g0v%' or geohash like 'wx4g0m%' or geohash like 'wx4g0q%'

6 or geohash like 'wx4g0y%' or geohash like 'wx4g0u%' or geohash like 'wx4g0k%')

匹配前5位并去除前6位的

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 SELECT id, lat, lon, geohash, updatetime FROMuser_location2 WHERE 1=1

3 and(4 geohash like 'wx4g0%' or geohash like 'wx4g2%' or geohash like 'wx4fb%'

5 or geohash like 'wx4g1%' or geohash like 'wx4ep%' or geohash like 'wx4er%'

6 or geohash like 'wx4g3%' or geohash like 'wx4fc%' or geohash like 'wx4dz%')7 and(8 geohash not like 'wx4g0t%' or geohash not like 'wx4g0w%' or geohash not like 'wx4g0s%'

9 or geohash not like 'wx4g0v%' or geohash not like 'wx4g0m%' or geohash not like 'wx4g0q%'

10 or geohash not like 'wx4g0y%' or geohash not like 'wx4g0u%' or geohash not like 'wx4g0k%'

11 )

View Code

这在数据层次一次性搜索增加了比较次数num*6倍。而事实上,我想做缓存的话,key=6和key=5的缓存存在被包含与包含的关系。理想的状态应该是:key=5的所有数据缓存,key=6的缓存持有key=5的缓存。这是一个对我来说复杂的缓存了。我也发现了,当我自习研究某项技术的时候什么都不会,换句话说自己就是代码搬运工而已。

现在的做法是直接缓存数据。以后升级redis了再考虑别的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java 身边距离怎么查询_附近的人位置距离计算方法 的相关文章

  • Linux 或者 Docker 容器通过 date 设置系统时间

    目录 1 Linux 2 Docker 容器 2 1 进入容器内部修改 2 2 可能会遇到的问题 1 Linux 要在Linux系统中设置日期和时间 可以使用date命令 使用以下命令格式来设置日期和时间 sudo date s YYYY
  • kubernetes二进制单节点和多节点部署(多节点+dashbord)

    kubernetes二进制单节点和多节点部署 多节点 dashbord kubernetes单节点部署 环境准备 在 master01 节点上操作 上传 master zip 和 k8s cert sh 到 opt k8s 目录中 解压 m
  • YOLOv5 Focus C3 各模块详解及代码实现

    目录 yolov5s yaml yolov5s yaml基本参数含义 一些基本参数 BackBone Head Focus 一 Focus模块的作用 Focus的参数量 Yolov3和Yolov5的改进对比 关于Focus的补充 网络结构图
  • 轻量级人像分割深度学习模型PP-HumanSeg树莓派部署

    人像分割是图像分割领域的高频应用 PaddleSeg推出在大规模人像数据上训练的人像分割系列模型PP HumanSeg 包括超轻量级模型PP HumanSeg Lite 满足在服务端 移动端 Web端多种使用场景的需求 本项目将PP Hum
  • Ceph分布式存储详解

    一 Ceph概述 1 存储发展史 企业中使用存储按照其功能 使用场景 一直在持续发展和迭代 大体上可以分为四个阶段 DAS Direct Attached Storage 即直连存储 第一代存储系统 通过SCSI总线扩展至一个外部的存储 磁
  • ChatGPT泄露用户聊天记录标题;Adobe加入AIGC战局;阿里大模型前带头人杨红霞加盟字节跳动丨每日大事件...

    数据智能产业创新服务媒体 聚焦数智 改变商业 企业动态 诸葛智能推出 诸葛CDP 2 0 等三大产品升级 3月22日 容联云旗下场景化数据智能服务商 诸葛智能 举办2023春季发布会 推出客户数据管理平台 诸葛CDP 2 0 一站式用户行为
  • freemarker动态生成word和pdf

    1 使用freemarker生成word freemarker生成word的方法网上有很多 比较简单 基本上都差不多 所需工具 freemarker
  • Python爬虫之Js逆向案例(3)-X品牌手机社区

    声明 XX手机社区加密逆向分析仅用于研究和学习 这篇文章的学习内容是以XX手机社区为案例 对JS逆向的整个过程进行详细分析 下面会进行以下几步进行分析 下方演示过程全部使用chrome浏览器 锁定关键接口 锁定关键字段 破解关键字段 pyt
  • (Java)leetcode-4 Median of Two Sorted Arrays(寻找两个正序数组的中位数)

    题目描述 给定两个大小为 m 和 n 的正序 从小到大 数组 nums1 和 nums2 请你找出这两个正序数组的中位数 并且要求算法的时间复杂度为 O log m n 你可以假设 nums1 和 nums2 不会同时为空 示例 1 num
  • 三步实现Android任意控件悬浮效果

    Tag 项目介绍 之前做项目的时候实现的一个悬浮效果 如图 可能不够清晰 接下来就是实现效果 如图所示 demo直接用的截图 原理很简单 用RecyclerView addHeaderView的方式实现 实现步骤 1 添加依赖 compil
  • 树莓派——linux内核与驱动

    文章目录 Linux内核基础框架 内核结构框图 linux系统架构 shell 驱动 为什么要学习写驱动 什么是驱动 硬件设备分类 文件名与设备号 驱动结构框图的认知 内核的 sys open sys read 会做什么 驱动程序开发步骤
  • 过采样和欠采样

    一 采样定理 只要采样频率高于信号最高频率的两倍 就可以从采样信号中恢复出原始信号 二 过采样和欠采样 1 采样频率高于信号最高频率的两倍 这种采样被称为过采样 2 采样频率低于信号最高频率的两倍 这种采样被称为欠采样 三 基带信号和频带信
  • 计算机网络知识点汇总

    主要内容 基本概念 物理层 数据链路层 网络层 传输层 应用层 一 基本概念 计算机网络 按照某种协议进行数据通信 实现硬件资源和软件资源的共享 分类 分布范围 使用者 交换技术 拓扑结构 传输技术 计算机网络的体系结构 ISO OSI参考
  • @RequestParam、@PathVariable、@RequestBody、@ResponseBody注解辨析

    RequestParam RequestParam 将请求参数绑定到你控制器的方法参数上 是springmvc中接收普通参数的注解 例如 defaultValue为给name设定默认值 RequestParam中的value值必须跟http
  • UML笔记

    UML笔记 枫叶云笔记
  • GLSL-TBN矩阵

    TBN矩阵 一 简述 1 1 TBN矩阵作用 我们研究一个矩阵的时候通常需要了解一个矩阵是从哪一个空间或者说矩阵而来的 如果搜索一下TBN矩阵运算公式可以发现其决定于物体坐标系下的顶点和纹理坐标系下的纹理坐标 想到这里我们需要明确TBN运算
  • 数据库服务版本升级

    数据库版本升级方法 第一种方法 本地升级 数据库服务5 6 5 7 8 0 停库 第二种方法 迁移升级 数据库服务数据迁移到另一台新的数据库服务中 旧版数据库服务地址 10 0 0 51 网络停止 新版数据库服务地址 10 0 0 51 8
  • AR回归模型详解

    转 http geodesy blog sohu com 273714573 html 1 自回归模型的定义 自回归模型 Autoregressive Model 是用自身做回归变量的过程 即利用前期若干时刻的随机变量的线性组合来描述以后某
  • JavaJDK实现无钥签名根证书与沙箱安全机制

    1 起因 接到项目经理的需求 项目有涉及文件的上传 需要把上传的文件进行数字签名 简称无钥签名 然后对签名后的文件进行无钥验证 对于从来没有听过无钥签名的我感觉很懵 后面就去上网查数字签名是java的哪一块 得到以下结果 Java里其实有两

随机推荐

  • 9.1 Linux配置网络服务

    9 1 1 配置网络参数 9 1 2 创建网络会话 9 1 3 绑定两块网卡 第1步 第2步 第3步 第4步 9 1 1 配置网络参数 在 Linux 系统上配置服务 在此之前 必须先保证主机之间能够顺畅地通信 如果网络不通 即便服务部署得
  • 朱嘉明:区块链成为经济转型、形成产业新业态的技术手段

    文章来自巴比特https www 8btc com live 14 在港珠澳大桥开通 以及粤港澳大湾区规划发展的效应下 珠海和澳门的城市发展进入到一个里程碑式的协同新阶段 尤其是拥有中央战略定位加持的国家级新区 横琴 早已吹响创新发展的号角
  • 第二章:恶意软件动态分析基础

    文章目录 前言 动态分析的局限 前言 静态分析侧重的是恶意软件在文件形式中的表现 动态分析则在一个安全 受控的环境中运行恶意软件以查看其行为方式 通过动态分析 我们可以绕过常见的静态分析障碍 例如加壳 混淆 以更直观地了解给定恶意软件样本的
  • Java 中数据结构LinkedList的用法

    LinkList 链表 Linked list 是一种常见的基础数据结构 是一种线性表 但是并不会按线性的顺序存储数据 而是在每一个节点里存到下一个节点的地址 链表可分为单向链表和双向链表 一个单向链表包含两个值 当前节点的值和一个指向下一
  • IDEA创建父项目和子项目

    一 创建父项目 1 首先在IDEA中使用Spring Initializr的方式创建一个Springboot的工程 点击File gt New gt Project gt Spring Initializr gt Next 2 Projec
  • 首期 OSCHINA 季度软件评选活动正式开启,快来投票吧!

    gt https www oschina net project 2020 q1 project 上周我们发出了 OSCHINA 开源软件趋势榜 即将上线的通知 并收到不少软件推荐 首先要感谢大家的热情参与 若有对此还不了解的朋友 OSCH
  • CSS 滑动门

    先来体会下现实中的滑动门 或者你可以叫做推拉门 滑动门出现的背景 制作网页时 为了美观 常常需要为网页元素设置特殊形状的背景 比如微信导航栏 有凸起和凹下去的感觉 最大的问题是里面的字数不一样多 咋办 为了使各种特殊形状的背景能够自适应元素
  • TypeScript 基础 — Null 和 Undefined

    null 和 undefined 都有各自的类型名称 这些类型本身没有用处 因为我们只能将 null 和 undefined 赋值给定义为 null 或 undefined 类型的变量 let u undefined undefined u
  • Mac os系统下使用python3与Django进行网站搭建-2

    后台管理 站点分为内容发布和公共访问两部分 内容发布的部分是由网站的管理员负责查看 添加 修改 删除数据 开发这些重复的功能是一件繁琐的工作 所以Django能够根据定义的模型类自动地生成管理模块 使用Django的管理模块 需要按照如下步
  • 智能随访系统:提升患者综合服务能力和就医体验,提高医院品牌价值与服务质量

    随着互联网技术的不断发展以及 全民健康 全生命周期管理 概念的深化落实 随访作为医疗过程中的闭环环节 医院传统的人工电话随访方式已不能适应需求 将逐渐被智能化随访系统替代 智能化随访是指结合互联网等主流技术 以专业的随访知识库为基础 提供以
  • uni-app微信小程序开发自定义select下拉多选内容篇

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 技术框架公司的选型 uni app uni ui vue3 vite4 ts 需求分析 微信小程序 uni ui内容 1 创建一个自定义的下拉
  • 基于个人开发的C++MySQL插件使用UE4蓝图连接MySQL数据库

    关于UE4连接数据库 其实很简单 本质上就是使用c 来建立DB操作 再通过封装成蓝图可调用的函数即可 当然一般网络游戏是不需要在蓝图中连接数据库的 因为db操作放在客户端来做是不安全 也是不合理的 试想一下 我如果把你的游戏客户端破解了 是
  • 【推荐算法】FM模型:Factorization Machines

    1 线性回归 在介绍FM之前 我们先简单回顾以下线性回归 回归分析是一种预测性的建模技术 它研究的是因变量 目标 和自变量 预测器 之间的关系 这种技术通常用于预测分析 时间序列模型以及发现变量之间的因果关系 通常使用曲线 直线来拟合数据点
  • Jmeter之json提取器

    目标 步骤 添加 线程组 HTTP 请求 后置处理器 JSON 提取器 配置 引用名称 匹配后的数据要存储的变量名 JSON path json 路径 weatherinfo city 引用 直接引用变量名即可
  • 代码思维怎么训练

    做一个基础页面 表格 表单 导航条 模态框 轮播图 做一个主页 顶部是导航条 导航条的下面是轮播图 右上角是一个注册按钮 点击以后 弹出一个注册的模态框 1 记录思路 2 思路转成注释 越详细越好 3 看着注释写代码 4 如果写不下去 继续
  • 数据库常用SQL语句(二):多表连接查询

    前面主要介绍了单表操作时的相关查询语句 接下来介绍一下多表之间的关系 这里主要是多表数据记录的查询 也就是如何在一个查询语句中显示多张表的数据 这也叫多表数据记录的连接查询 在实现连接查询时 首先是将两个或两个以上的表按照某种关系连接起来
  • nfc(近距离无线通讯技术)

    这个技术由非接触式射频识别 RFID 演变而来 由 飞利浦半导体 现恩智浦半导体 诺基亚和 索尼共同研制开发 其基础是RFID及互连技术 近场通信 Near Field Communication NFC 是一种短距高频的无线电技术 在13
  • 零基础学区块链专栏文章目录

    前往老猿Python博文目录 零基础学区块链专栏 为免费专栏 基于老猿自己零基础学习区块链的知识总结 因此文章一定是循序渐进的介绍区块链相关知识 供类似老猿这种有一定计算机基础但区块链知识为零的同好们参考 但老猿介绍的内容都是概念性的基础知
  • 让你的应用支持新iPad的Retina显示屏

    一 应用图片 标准iOS控件里的图片资源 苹果已经做了相应的升级 我们需要操心的是应用自己的图片资源 就像当初为了支持iPhone 4而制作的 2x高分辨率版本 译者 以下简称高分 图片一样 我们要为iPad应用中的图片制作对应的高分版本
  • java 身边距离怎么查询_附近的人位置距离计算方法

    附近的人的位置用经纬度表示 然后通过两点的经纬度计算距离 根据网上的推荐 最终采用geohash geohash的实现java版 1 importjava util BitSet 2 importjava util HashMap 3 im