浙江建设厅继续教育网站建设网站业务竞争大
浙江建设厅继续教育网站,建设网站业务竞争大,大型网站seo策略,沈阳做网站的企业概述
在业务中经常会遇到用户拖拽排序的场景#xff0c;那么拖拽后的结果肯定需要一个值来定义这个排序结果#xff1b;
一般都是用存数字来代替#xff1b;但当排序发生变更时#xff0c;连续的数字不太好维护#xff0c;比如1#xff0c;2#xff0c;3#xff0c;将3…概述在业务中经常会遇到用户拖拽排序的场景那么拖拽后的结果肯定需要一个值来定义这个排序结果一般都是用存数字来代替但当排序发生变更时连续的数字不太好维护比如123将3拖拽到1和2之间时这个sort值应该是多少呢如果引入浮点数那么浮点数的精度会一直膨胀而后端db中sort字段的精度一般是固定的并且不能无限制膨胀所以在查找了相关资料后最后采用的是中值法定义a,b,c三个sort分别是100020003000当abc - acb时c.sort (a.sort b.sort)/2并在后端update这个sort时比较前后的sort是否阈值数值当时进行重排即a.sort 1000,c.sort 2000,b.sort 3000同时增加版本号字段增加乐观锁;然后最优的是结合websocket等方案进行多端同步如果存在多端操作同一个拖拽泳道的话比如飞书腾讯在线文档这种;我这边因为开发排期等原因综合比较下来只做了被动刷新即使用version字段在update sort时判断是否已经被其他人更新过了上述是中值法排序我的理解LexoRank排序在熟悉了中值法排序后我发现了另一个排序方式LexoRank排序之前排序的sort是采用的纯数字而LexoRank使用的字符串(字母数字比如77gf)简单了解下后发现其本质还是中值法只是在计算中值时会把字符串转成对应的十进制数比如下面12131和27ga的转换;这里不敲文字了,贴下手算的步骤好久没手算生疏了-。-还有一份demo代码packagecom.cloud.product.service.dto;importjava.math.BigInteger;publicclassLexoRank{privatefinal String alphabet;// e.g., 0123456789abcdefghijklmnopqrstuvwxyz//当前字符集长度privatefinal int base;privatefinal int length;// 固定秩字符串长度publicLexoRank(String alphabet,int length){this.alphabetalphabet;this.basealphabet.length();this.lengthlength;}// 将秩字符串转换为 BigIntegerpublicBigIntegertoBigInt(String rank){BigInteger valBigInteger.ZERO;for(int i0;irank.length();i){int idxalphabet.indexOf(rank.charAt(i));if(idx0)thrownewIllegalArgumentException(Invalid char in rank);valval.multiply(BigInteger.valueOf(base)).add(BigInteger.valueOf(idx));}returnval;}// 将 BigInteger 转回固定长度的秩字符串高位补零publicStringfromBigInt(BigInteger val){BigInteger bBigInteger.valueOf(base);char[]charsnewchar[length];BigInteger curval;for(int ilength-1;i0;i--){BigInteger[]drcur.divideAndRemainder(b);int idxdr[1].intValue();chars[i]alphabet.charAt(idx);curdr[0];}if(cur.compareTo(BigInteger.ZERO)0){thrownewIllegalArgumentException(Value too large for length);}returnnewString(chars);}// 生成初始秩例如中间值publicStringinitialRank(){//计算当前sort池下length下的最大至即base进制下 base^length值BigInteger maxBigInteger.valueOf(base).pow(length);BigInteger midmax.divide(BigInteger.valueOf(2));returnfromBigInt(mid);}// 在 a 和 b 之间生成一个秩假设 a bpublicStringbetween(String a,String b){BigInteger vatoBigInt(a);BigInteger vbtoBigInt(b);if(va.compareTo(vb)0)thrownewIllegalArgumentException(a must be b);BigInteger diffvb.subtract(va);if(diff.compareTo(BigInteger.ONE)0){// 无可用间隙需要重平衡调用外部重平衡逻辑thrownewIllegalStateException(No gap between ranks; rebalance required);}BigInteger midva.add(vb).divide(BigInteger.valueOf(2));returnfromBigInt(mid);}// 生成第一个或最后一个秩可用于插入到头尾publicStringbeforeFirst(){// 取最小可表示值的一半BigInteger minBigInteger.ZERO;BigInteger maxBigInteger.valueOf(base).pow(length);BigInteger valmax.divide(BigInteger.valueOf(10));// 例如靠前一点returnfromBigInt(val);}publicStringafterLast(){BigInteger maxBigInteger.valueOf(base).pow(length);BigInteger valmax.subtract(max.divide(BigInteger.valueOf(10)));returnfromBigInt(val);}// 简单示例publicstaticvoidmain(String[]args){String alphabet0123456789abcdefghijklmnopqrstuvwxyz;LexoRank lrnewLexoRank(alphabet,8);String r1lr.initialRank();String r2lr.afterLast();System.out.println(r1 r1);System.out.println(r2 r2);// 插入一个在 r1 和 r2 之间的秩String midlr.between(r1,r2);System.out.println(mid mid);// 连续插入示例注意可能触发 rebalancetry{String m2lr.between(r1,mid);System.out.println(m2 m2);}catch(IllegalStateException ex){System.out.println(需要重平衡: ex.getMessage());}}}