Я переношу нагрузку кода, чтобы остановить передачу байтов [] s, InputStreams и InputSuppliers и просто использовать ByteSource.
В настоящее время код вычисляет и ETag для данных, используя Arrays.hashCode в сыром байте [], что переводится с помощью ByteSource:
Arrays.hashCode(dataSource.read());
Проблема заключается в том, что dataSource.read()
в ByteArrayInputSource клонирует базовый байт [], что хуже, чем в настоящее время.
Я хотел бы использовать dataSource.hash(HashFunction)
но я хочу убедиться, что я не разрушаю ETags, сгенерированные с помощью hashCode, так как это приведет к недействительности кэша.
Кто-нибудь знает о HashFunction, который выполняет эту работу для меня?
Я не знаю какой-либо уже доступной функции HashFunction
которая будет делать то, что вы хотите, но ее очень легко написать. Что-то вроде:
public final class ByteArrayHashFunction extends AbstractStreamingHashFunction {
@Override
public Hasher newHasher() {
return new ByteArrayHasher();
}
@Override
public int bits() {
return 32;
}
private static final class ByteArrayHasher extends AbstractByteHasher {
private int hash = 1;
@Override
protected void update(byte b) {
hash = 31 * hash + b;
}
@Override
public HashCode hash() {
return HashCode.fromInt(hash);
}
}
}
Однако вам нужно будет скопировать несколько абстрактных классов из common.hash
в ваш собственный пакет.
AbstractNonStreamingHashFunction
, я настоятельно рекомендую использовать AbstractStreamingHashFunction
как я это сделал здесь. AbstractNonStreamingHashFunction
(как следует из «не потоковой» части имени) не работает хорошо для обработки потока байтов. Он предназначен для хеш-функций, которые должны обрабатывать набор байтов одновременно, и поэтому он буферизует все, что ему записано, до тех пор, пока вы не вызовете hash()
. С другой стороны, алгоритм, который использует Arrays.hashCode
, очень удобен для потоковой передачи.