Насколько я понимаю, вы хотите хэшировать списки строк, гарантируя, что никакие два разных списка не дадут одинакового результата. Это можно решить, не думая о хэш-функции вообще.
Вам нужна функция String f(List<String> l)
, где никакие два входных значения не приводят к одному и тому же выводу (функция инъективная от List<String>
до String
). Благодаря этому вы можете передать выходные данные своей хеш-функции и быть уверенными, что не будет никаких коллизий, поскольку сама хеш-функция обеспечивает это (обратите внимание, MD5 был сломан несколько лет назад, поэтому он может не подходить). Вот 2 способа реализации f
:
Преобразование в набор символов из набора
Самый простой способ - просто сопоставить каждый ввод с подмножеством набора символов String, который не включает ваш символ-разделитель:
public static String hex(String s) {
try {
String o = "";
for(byte b: s.getBytes("utf-8"))
o += String.format("%02x", b&0xff);
return o;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String f(String... l) {
if (l.length == 0) return "";
String o = hex(l[0]);
if (l.length == 1) return o;
for (int i = 1; i < l.length; i++) o += "#" + hex(l[i]);
return o;
}
f("a#","b") => 6123#62
f("a","#b") => 61#2362
Длина префикса
Это также довольно просто, но имеет тот недостаток, что его нельзя переписать для работы в потоке.
public static String prefix(String s) {
return s.length() + "." + s;
}
public static String f(String... l) {
if (l.length == 0) return "";
String o = prefix(l[0]);
if (l.length == 1) return o;
for (int i = 1; i < l.length; i++) o += "#" + prefix(l[i]);
return o;
}
f("a#","b") => 2.a##1.b
f("a","#b") => 1.a#2.#b