收到系统指定是35个以上的字符串,写入DB中要求不能超过27个长度(数据库不能加表也不能加字段)。
这样的指令一天有几万条(不重复),如果保证转换后的字符串也不是重复的(27个长度)。
而且转换后的 反向还能还原出系统指定(35个字符)
有什么好的算法吗?
大家回答时不要理论,把35长度字符串转27长度字符串 和 反向 27字符串还原35字符串算法给出。
参考这样来转化:
public static void main(String[] args) {
String data = "abcdefghi";
byte[] dataToByte = data.getBytes();
byte[] oneMB = new byte[1024];
// 本来的数据拷贝
for(int i=0;i<dataToByte.length;i++) {
oneMB[i] = dataToByte[i];
}
// 补全空格,对应的 byte 是32
for(int i=dataToByte.length;i<1024;i++) {
oneMB[i] = (byte)32;
}
}
建议增加子表,使用27长度的字段做关联映射.
做起来简单也没那么多风险.保证27位不重复还不是轻轻松松的事情
https://zhuanlan.zhihu.com/p/338832507
使用数制转换一下,传过来的字符串你看看里边的字符有多少,就当成一个多少数制的数,然后使用更高的数制来缩减总体长度。
比如那边只传小写字母,你可以当成一个26进制的数,然后自己定义使用60进制或者更高的来表达存储,只要保证你的27位能表达的数字大于客户传过来的ID表达的最大值就可以了。
可以按照如下的这个思路
假设您获得了长度为 N 的字符串 S 以及字符串 S hash[0][0...N-1] 的所有前缀的哈希值数组 .
原字符串 :String S = ABCDEFGHILJLMNOPORSTUVWXYZABCDEFGHIJ
hash[0][i] 表示以索引 i 结尾的字符串 S 的前缀的哈希值 . M 表示大的素数 . R 表示散列函数中使用的基数 .
您还获得了使用的哈希函数:
for(int i = 0; i < N; i++) {
hash[0][i] = ( (i > 0 ? hash[0][i - 1] : 0) * R + S.charAt(i) ) % M;
}
我们需要根据需要计算 hash[i][j] . 我们能否在 O(1) 中查找 S 的子字符串的哈希值,即 hash[i][j] 给出以上信息?
where, i,j > 0 and i,j < N
注意:数组 hash[][] 最初只包含字符串 S 前缀的预先计算哈希 hash[0][0....N-1] .
public class TestMainApplication {
public static void main(String[] args) {
int R = 27;
int N = 35;
int M = 2;
int[] hash=new int[40];
int len = 0;
// 如果这里的S 是有数字字母组成,则生成的
String S = "ABCDEFGHILJLMNOPORSTUVWXYZABCDEFGHIZ";
for (Character c:S.toCharArray()) {
int i = c.hashCode();
hash[len] = i ;
len++;
}
for(int i = 0; i < R; i++) {
hash[i] = ( (i > 0 ? hash[i - 1] : 0) * 35 + S.charAt(i) ) % M;
System.out.print(hash[i]);
}
}
}
}
}
先写一个,明天继续。
注 代码没有调试过,思路就是删除冗余的位来节约空间。
https://www.cnblogs.com/EasonJim/p/8256906.html
这个也不能保证唯一,只能说用比较好的方法保证尽量不重复,可以使用雪花算法进行生成然后映射
zip压缩?
35个长度的字符有没有限制,比如说只能是字母+数字,字符的范围很小的可以压缩。如果是任意字符的话,还是只能多做一个表进行映射了。或者考虑Hash,只不过要处理冲突。反正需要你根据业务场景取舍
如果原字符串中字符重复度较高,可能可以用哈夫曼编码或者简单的行程编码如(1A2B3C)这种
或者可以试试GZIPOutputStream,过短的字符串压缩后可能会比原字符串还大。
public static String compress(String str) {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes());
gzip.close();
return out.toString("ISO-8859-1");
}
public static void main(String[] args) throws IOException {
String string = "admin";
System.out.println("after compress:");
System.out.println(ZipUtil.compress(string));
}
一般这点长度的字符串用压缩算法没必要也没有用。拆分字符串,关联到一条记录或者直接加表字段长度最简单也有效
package compress;
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterOutputStream;
public class CompressionUtil {
public static String compressAndReturnB64(String text) throws IOException {
return new String(Base64.getEncoder().encode(compress(text))); } String(Base64.getEncoder().encode(compress(text))); }
public static String decompressB64(String b64Compressed) throws IOException {
byte [] decompressedBArray = decompress(Base64.getDecoder().decode(b64Compressed)); return new String(decompressedBArray, StandardCharsets.UTF_8); } String(decompressedBArray, StandardCharsets.UTF_8); }
public static byte [] compress(String text) throws IOException {
return compress(text.getBytes()); } compress(text.getBytes()); }
public static byte [] compress( byte [] bArray) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(); try (DeflaterOutputStream dos = new DeflaterOutputStream(os)) {
dos.write(bArray); }
return os.toByteArray(); } os.toByteArray(); }
public static byte [] decompress( byte [] compressedTxt) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(); try (OutputStream ios = new InflaterOutputStream(os)) {
ios.write(compressedTxt); }
return os.toByteArray(); } os.toByteArray(); }
}
可以搜索一下字符串压缩算法