编码生成 进位简洁版 AAAA-01->ZZZZ-99
背景:
需求要生成满足AAAA-01,AAAA-02....AAAA-99....ZZZZ-99格式的编码。
tip:
有现成的可用CV,但是这两天比较闲。自己手撸,当前进位存储地方不在考虑范围,存redis,mem-cache,db,内存随意。只考虑进位
简单描述:分三部分1.前缀类 2.后缀类 3.进位工具
1.前缀类
package com.coax.demo.handler.systemcode.model; import com.coax.demo.handler.systemcode.tool.CodePrefixTool; import lombok.AccessLevel; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import lombok.experimental.FieldDefaults; /** * 编码前4位自增 AAAA->AAAB->....->ZZZZ * * @author <a href="tomail:coax@outlook.it">chengxiaohong<a/> * @version v1.5 * @since 2020/7/27 */ @Data @Accessors(chain = true) @FieldDefaults(level = AccessLevel.PRIVATE) @NoArgsConstructor public class CodePrefix implements SystemCode { /** * 自增区间 */ String current; public CodePrefix(String current) { this.current = current; } /** * 获取下一个code CodePrefix * * @return String */ @Override public String next() { return CodePrefixTool.up(this.current); } }
2.后缀类
package com.coax.demo.handler.systemcode.model; import lombok.AccessLevel; import lombok.Data; import lombok.experimental.Accessors; import lombok.experimental.FieldDefaults; import org.apache.commons.lang3.StringUtils; /** * * 编码后2位循环 01->99->01->99 * * @author <a href="tomail:coax@outlook.it">chengxiaohong<a/> * @version v1.5 * @since 2020/7/27 */ @Data @Accessors(chain = true) @FieldDefaults(level = AccessLevel.PRIVATE) public class CodeSuffix implements SystemCode { private CodeSuffix() { } /** * 循环开区间 */ private static int PART_START = 0, PART_END = 99; /** * 编码后区间 */ int current; public CodeSuffix(int current) { this.current = current; } /** * 获取下一位后编码 * * @return 下一位后编码 */ public String next() { int r = current; if (PART_END <= this.current || PART_START >= this.current) { r = PART_START; } return StringUtils.leftPad(String.valueOf(r + 1), 2, String.valueOf(0)); } /** * 前缀是否需要进位 和 后缀是否重置 :条件(到达最大值) * * @param suffix 后缀值 * @return boolean */ public static boolean resetCheck(int suffix) { return suffix == PART_END; } }
3. 进位工具类
package com.coax.demo.handler.systemcode.tool; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * 前缀映射类 * * @author <a href="tomail:coax@outlook.it">chengxiaohong<a/> * @version v1.5 * @since 2020/7/27 */ public class CodePrefixTool { private CodePrefixTool() { } /** * 自增数据数组源 */ private static final char[] PREFIX_SOURCES_ARRAY = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; private static final String PREFIX_SOURCES = String.copyValueOf(PREFIX_SOURCES_ARRAY); private static final int END_MAX = 25; private static final int SIZE = 4; /** * 自增开区间 */ private static final int[] START = {0, 0, 0, 0}; /** * 自增闭区间 */ private static final int[] END = {END_MAX, END_MAX, END_MAX, END_MAX}; /** * 向上偏移一位 AAAA->AAAB * * @return String */ public static String up(String current) { final int[] desc = checkAndGet(current); return IntStream.rangeClosed(0, desc.length - 1).mapToObj(i -> { return String.valueOf(PREFIX_SOURCES_ARRAY[desc[i]]); }).collect(Collectors.joining()); } /** * 向下偏移一位 AAAB->AAAA * * @return String */ public static String down(String sources) { //FIXME:程小洪 2020/7/27 未实现 return null; } private static int[] checkAndGet(String sources) { //初始化 if (StringUtils.isBlank(sources)) { return START; } //长度校验 if (sources.length() != START.length) { throw new IllegalArgumentException( String.format("源数据长度不满足,目标长度:%d,结果长度:%d", START.length, sources.length()) ); } //可用性校验 大小写兼容 char[] sourcesArray = sources.toUpperCase().toCharArray(); for (char c : sourcesArray) { if (PREFIX_SOURCES.indexOf(c) == -1) { throw new IllegalArgumentException("源数据应只能是大写字母"); } } int[] ret = new int[SIZE]; for (int i = 0; i < sourcesArray.length; i++) { char c = sourcesArray[i]; ret[i] = PREFIX_SOURCES.indexOf(c); } if (Arrays.equals(ret, END)) { throw new IllegalArgumentException("此规则已达到最大取值范围"); } return exePlus(ret, ret.length - 1, false); } /** * 向上偏移一位 * * @param sources 源数据 * @param currentCyc 当次递归入栈次数(sources 长度向下递减取反) * @param frontBiz 上次是否增加 * @return int[] */ private static int[] exePlus(int[] sources, int currentCyc, boolean frontBiz) { //是否需要偏移 sources[currentCyc] = sources[currentCyc] + (frontBiz ? 0 : 1); //偏移进位 if (sources[currentCyc] == PREFIX_SOURCES_ARRAY.length) { sources[currentCyc] = 0; sources[currentCyc - 1] = sources[currentCyc - 1] + 1; //偏移进位溢出 if (sources[currentCyc - 1] == PREFIX_SOURCES_ARRAY.length) { exePlus(sources, currentCyc - 1, true); } } else { return sources; } return sources; } }
4.前缀以及编码接口 其实没有必要。只有一个接口方法
package com.coax.demo.handler.systemcode.model; /** * @author <a href="tomail:coax@outlook.it">chengxiaohong<a/> * @version v1.5 * @since 2020/7/27 */ public interface SystemCode { /** * 获取下一个code * * @return String */ String next(); }
跑一下测试:
package com.coax.demo; import com.coax.demo.systemcode.model.CodeSuffix; import com.coax.demo.systemcode.tool.CodePrefixTool; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.runners.MockitoJUnitRunner; /** * 系统编码生成组件测试 * * @author <a href="tomail:coax@outlook.it">chengxiaohong<a/> * @version v1.5 * @since 2020/7/27 */ @RunWith(MockitoJUnitRunner.class) public class GoodsSystemCodeHandler { /** * 空值 初始化测试 */ @Test public void codePrefixTool1() { CodePrefixTool.up(null); } /** * 入参长度不足测试 */ @Test(expected = IllegalArgumentException.class) public void codePrefixTool2() { CodePrefixTool.up("AAA"); } /** * 非法入参测试 */ @Test(expected = IllegalArgumentException.class) public void codePrefixTool3() { CodePrefixTool.up("aaa"); } /** * 最大取值范围测试 */ @Test(expected = IllegalArgumentException.class) public void codePrefixTool4() { CodePrefixTool.up("ZZZZ"); } /** * 正常取值 */ @Test() public void codePrefixTool5() { System.out.println(CodePrefixTool.up("AAAA")); } /** * 跨界取值 */ @Test() public void codePrefixTool6() { System.out.println(CodePrefixTool.up("AAZZ")); } /** * 自增后缀测试 */ @Test public void CodeSuffix1() { CodeSuffix codeSuffix = new CodeSuffix(0); System.out.println(codeSuffix.next()); codeSuffix = new CodeSuffix(100); System.out.println(codeSuffix.next()); codeSuffix = new CodeSuffix(99); System.out.println(codeSuffix.next()); codeSuffix = new CodeSuffix(10); System.out.println(codeSuffix.next()); } }
emmm:虽然烂得一匹。勉强交差,可以回家打游戏去了 。还有 满99进位就不贴了。写得太丑