java 如何将一个超过35个长度的字符串转化为 27个长度,保证转化后的字符串唯一

收到系统指定是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]);
        }
    }
}

img


参照字符表,共64个打印字符且第4和第7位均为0
将s1压缩到s2
void fun1(char *s1, char *s2)
{
int i = 0, l = 0;
int b1 = 0, b2 = 0;
int charIdx = 0, bitIdx = 0;
unsigned char s[35] = {0};
memset(s2, 0, 27);
for(i = 0; i < 35 i++)
{
if(s1[i] == 0)
{
l = i;
break;
}
s[i] = s1[i] & 0x0F;
s[i] |= (s1[i] & 0xF0) >> 1;
}
for(i = 0; i < l; i++)
{
b1 = 2 - bitIdx;
b2 = bitIdx + 6 - 8;
bitIdx += 6;
if (b1 >= 0)
{
s2[charIdx] |= s[i] << b1;
}
else
{
bitIdx -= 8;
s2[charIdx] |= s[i] >> b2;
charIdx++;
s2[charIdx] |= s[i] << (b2 + 2)
}

}

}
先写一个,明天继续。
注 代码没有调试过,思路就是删除冗余的位来节约空间。

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));
    }

一般这点长度的字符串用压缩算法没必要也没有用。拆分字符串,关联到一条记录或者直接加表字段长度最简单也有效

  1. 32位的字符串 是什么格式的?纯数字?纯字母?数字+字母还是什么。
  2. 压缩之后的字符串 有什么要求吗?还是唯一就可以
  3. 32位的字符串,会不会有重复的字符,还是所有的字符都不会重复

https://blog.csdn.net/weixin_32081079/article/details/114710687?spm=1005.2026.3001.5635&utm_medium=distribute.pc_relevant_ask_down.none-task-blog-2~default~OPENSEARCH~Rate-5.pc_feed_download_top3ask&depth_1-utm_source=distribute.pc_relevant_ask_down.none-task-blog-2~default~OPENSEARCH~Rate-5.pc_feed_download_top3ask


 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();   }
 }

可以搜索一下字符串压缩算法