使用JAVA生成一个字母+数字的自增序列
基本需求
需求:需要生成一个6位的自增序列,并且自增序列中的字母排除掉IOSVZ
格式要求:
- 先用数字进行自增,如:000001到999999。
- 如果6位都是数字并且达到最大值999999时,再次递增时,把第一位修改位字母A,后面5位从00001开始,如:A00001到A99999,如果后5位达到最大值99999时,首位字母自增为B,以此类推首位字母最大是Y。
- 当首位字母是Y,数字达到99999,前两位修改为字母YA,后4位是数字从0001开始,最大是YY9999。再以此类推生成最大的自增序列是YYYYYY。
示例输出:000001 000002 … 999999 A00001 A00002 … A99999 B00000 B00001 … B99999 … Y00000 Y00001 … Y99999 YA0000 … YYYYYY
import java.util.HashMap;
import java.util.Map;
public class SequenceGenerator {
// 定义要排除的字符数组,这些字符可能会在某些特定的场景下引起混淆或不希望被使用
private static final char[] EXCLUDE_CHARS = {'I', 'O', 'S', 'V', 'Z'};
// 定义字母表数组,包含了A到Z的所有大写字母,用于字符索引映射的初始化
private static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
// 定义字符索引映射,将每个字母映射到其在字母表中的位置,便于快速查找和处理
private static final Map<Character, Integer> CHAR_INDEX_MAP = new HashMap<>();
// 定义一个布尔数组,用于快速判断一个字符是否是有效的(即是否在字母表中且不在排除列表中)
// 128是ASCII字符集的大小,因此这个数组覆盖了所有ASCII字符的判断
private static final boolean[] VALID_CHAR = new boolean[128];
// 静态初始化块,用于初始化字符映射和有效字符数组
static {
// 遍历ALPHABET数组,为每个字符在CHAR_INDEX_MAP中创建映射,并在VALID_CHAR中标记为有效
for (int i = 0; i < ALPHABET.length; i++) {
CHAR_INDEX_MAP.put(ALPHABET[i], i);
VALID_CHAR[ALPHABET[i]] = true;
}
// 遍历EXCLUDE_CHARS数组,将这些字符在VALID_CHAR中标记为无效
for (char c : EXCLUDE_CHARS) {
VALID_CHAR[c] = false;
}
// 遍历数字字符(0-9),在VALID_CHAR中标记为有效
for (int i = '0'; i <= '9'; i++) {
VALID_CHAR[i] = true;
}
}
/*
* 需求:需要生成一个6位的自增序列,并且自增序列中的字母排除掉IOSVZ
* 格式要求:先用数字进行自增,如:000001到999999。
* 如果6位都是数字并且达到最大值999999时,再次递增时,把第一位修改位字母A,后面5位从00001开始,如:A00001到A99999,如果后5位达到最大值99999时,首位字母自增为B,以此类推首位字母最大是Y。
* 当首位字母是Y,数字达到99999,前两位修改为字母YA,后4位是数字从0001开始,最大是YY9999。再以此类推生成最大的自增序列是YYYYYY。
* 示例输出:000001 000002 ... 999999 A00001 A00002 ... A99999 B00000 B00001 ... B99999 ... Y00000 Y00001 ... Y99999 YA0000 ... YYYYYY
*/
public static String increment(String sequence) {
int maxLength = sequence.length();
// 验证输入字符的有效性
for (char c : sequence.toCharArray()) {
if (!VALID_CHAR[c]) {
throw new IllegalArgumentException("Invalid character in sequence: " + c);
}
}
// 检查是否全为数字
if (sequence.matches("\\d{" + maxLength + "}")) {
long num = Long.parseLong(sequence);
if (num < Math.pow(10, maxLength)) {
return String.format("%0"+maxLength+"d", num + 1);
}
}
// 处理包含字母的情况
StringBuilder sb = new StringBuilder(sequence);
int index = maxLength-1;
while (index >= 0) {
char c = sb.charAt(index);
if (Character.isDigit(c) && !(index==0 && c=='9')) {
if (c == '9') {
sb.setCharAt(index, '0');
index--;
} else {
sb.setCharAt(index, (char) (c + 1));
break;
}
} else {
//当前字符为字母,判断下一个字母是否可用,如果不可用,则将当前字母替换为下一个可用字母,并将后续的数字字符重置为0,然后继续处理前一个字符。
//如果当前字母集合最后一个,并且不可用时,
int letterIndex = getLetterIndex(c);
if (letterIndex < ALPHABET.length - 1) {
char nextValidChar = getNextValidChar(ALPHABET[letterIndex + 1]);
if(!VALID_CHAR[nextValidChar] && ALPHABET[ALPHABET.length-1]==nextValidChar){
sb.setCharAt(++index, getNextValidChar('A'));
}else {
sb.setCharAt(index, nextValidChar);
}
// 重置后续的数字字符
for (int j = index + 1; j < maxLength; j++) {
sb.setCharAt(j,nextValidChar==ALPHABET[0] && j==maxLength-1?'1':'0');
}
break;
} else {
sb.setCharAt(index, getNextValidChar('A'));
index--;
}
}
}
if (index < 0) {
throw new IllegalStateException("Sequence overflow: " + sequence);
}
return sb.toString();
}
/**
* 获取字符在字母表中的索引
*
* @param c 要查询的字符
* @return 字符在字母表中的索引,如果不存在,则返回-1
*/
private static int getLetterIndex(char c) {
Integer index = CHAR_INDEX_MAP.get(c);
if (index == null) {
index = -1;
}
return index;
}
/**
* 获取给定字符的下一个有效字符
*
* @param c 起始字符
* @return 下一个有效字符
*/
private static char getNextValidChar(char c) {
while (c < 'Z' && !VALID_CHAR[c]) {
c++;
}
return c;
}
public static void main(String[] args) {
String start = "999989";
for (int i = 0; i <= 1000; i++) { // 生成100个序列
System.out.println(start);
start = increment(start);
}
}
}