mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
48eec2a8ae
commit
9ab3397a2f
@ -17,6 +17,9 @@ import java.util.Arrays;
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>{
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static CityHash INSTANCE = new CityHash();
|
||||
|
||||
// Some primes between 2^63 and 2^64 for various uses.
|
||||
@ -50,46 +53,46 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
|
||||
// len > 24
|
||||
int h = len, g = c1 * len, f = g;
|
||||
int a0 = rotate32(fetch32(data, len - 4) * c1, 17) * c2;
|
||||
int a1 = rotate32(fetch32(data, len - 8) * c1, 17) * c2;
|
||||
int a2 = rotate32(fetch32(data, len - 16) * c1, 17) * c2;
|
||||
int a3 = rotate32(fetch32(data, len - 12) * c1, 17) * c2;
|
||||
int a4 = rotate32(fetch32(data, len - 20) * c1, 17) * c2;
|
||||
int a0 = Integer.rotateRight(fetch32(data, len - 4) * c1, 17) * c2;
|
||||
int a1 = Integer.rotateRight(fetch32(data, len - 8) * c1, 17) * c2;
|
||||
int a2 = Integer.rotateRight(fetch32(data, len - 16) * c1, 17) * c2;
|
||||
int a3 = Integer.rotateRight(fetch32(data, len - 12) * c1, 17) * c2;
|
||||
int a4 = Integer.rotateRight(fetch32(data, len - 20) * c1, 17) * c2;
|
||||
h ^= a0;
|
||||
h = rotate32(h, 19);
|
||||
h = Integer.rotateRight(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h ^= a2;
|
||||
h = rotate32(h, 19);
|
||||
h = Integer.rotateRight(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= a1;
|
||||
g = rotate32(g, 19);
|
||||
g = Integer.rotateRight(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
g ^= a3;
|
||||
g = rotate32(g, 19);
|
||||
g = Integer.rotateRight(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
f += a4;
|
||||
f = rotate32(f, 19);
|
||||
f = Integer.rotateRight(f, 19);
|
||||
f = f * 5 + 0xe6546b64;
|
||||
int iters = (len - 1) / 20;
|
||||
|
||||
int pos = 0;
|
||||
do {
|
||||
a0 = rotate32(fetch32(data, pos) * c1, 17) * c2;
|
||||
a0 = Integer.rotateRight(fetch32(data, pos) * c1, 17) * c2;
|
||||
a1 = fetch32(data, pos + 4);
|
||||
a2 = rotate32(fetch32(data, pos + 8) * c1, 17) * c2;
|
||||
a3 = rotate32(fetch32(data, pos + 12) * c1, 17) * c2;
|
||||
a2 = Integer.rotateRight(fetch32(data, pos + 8) * c1, 17) * c2;
|
||||
a3 = Integer.rotateRight(fetch32(data, pos + 12) * c1, 17) * c2;
|
||||
a4 = fetch32(data, pos + 16);
|
||||
h ^= a0;
|
||||
h = rotate32(h, 18);
|
||||
h = Integer.rotateRight(h, 18);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
f += a1;
|
||||
f = rotate32(f, 19);
|
||||
f = Integer.rotateRight(f, 19);
|
||||
f = f * c1;
|
||||
g += a2;
|
||||
g = rotate32(g, 18);
|
||||
g = Integer.rotateRight(g, 18);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
h ^= a3 + a1;
|
||||
h = rotate32(h, 19);
|
||||
h = Integer.rotateRight(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= a4;
|
||||
g = Integer.reverseBytes(g) * 5;
|
||||
@ -104,16 +107,16 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
pos += 20;
|
||||
} while (--iters != 0);
|
||||
|
||||
g = rotate32(g, 11) * c1;
|
||||
g = rotate32(g, 17) * c1;
|
||||
f = rotate32(f, 11) * c1;
|
||||
f = rotate32(f, 17) * c1;
|
||||
h = rotate32(h + g, 19);
|
||||
g = Integer.rotateRight(g, 11) * c1;
|
||||
g = Integer.rotateRight(g, 17) * c1;
|
||||
f = Integer.rotateRight(f, 11) * c1;
|
||||
f = Integer.rotateRight(f, 17) * c1;
|
||||
h = Integer.rotateRight(h + g, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = rotate32(h, 17) * c1;
|
||||
h = rotate32(h + f, 19);
|
||||
h = Integer.rotateRight(h, 17) * c1;
|
||||
h = Integer.rotateRight(h + f, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = rotate32(h, 17) * c1;
|
||||
h = Integer.rotateRight(h, 17) * c1;
|
||||
return h;
|
||||
}
|
||||
|
||||
@ -149,11 +152,11 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
len = (len - 1) & ~63;
|
||||
int pos = 0;
|
||||
do {
|
||||
x = rotate64(x + y + v.getLowValue() + fetch64(data, pos + 8), 37) * k1;
|
||||
y = rotate64(y + v.getHighValue() + fetch64(data, pos + 48), 42) * k1;
|
||||
x = Long.rotateRight(x + y + v.getLowValue() + fetch64(data, pos + 8), 37) * k1;
|
||||
y = Long.rotateRight(y + v.getHighValue() + fetch64(data, pos + 48), 42) * k1;
|
||||
x ^= w.getHighValue();
|
||||
y += v.getLowValue() + fetch64(data, pos + 40);
|
||||
z = rotate64(z + w.getLowValue(), 33) * k1;
|
||||
z = Long.rotateRight(z + w.getLowValue(), 33) * k1;
|
||||
v = weakHashLen32WithSeeds(data, pos, v.getHighValue() * k1, x + w.getLowValue());
|
||||
w = weakHashLen32WithSeeds(data, pos + 32, z + w.getHighValue(), y + fetch64(data, pos + 16));
|
||||
// swap z,x value
|
||||
@ -231,19 +234,19 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
long x = seed.getLowValue();
|
||||
long y = seed.getHighValue();
|
||||
long z = len * k1;
|
||||
v.setLowValue(rotate64(y ^ k1, 49) * k1 + fetch64(byteArray, start));
|
||||
v.setHighValue(rotate64(v.getLowValue(), 42) * k1 + fetch64(byteArray, start + 8));
|
||||
w.setLowValue(rotate64(y + z, 35) * k1 + x);
|
||||
w.setHighValue(rotate64(x + fetch64(byteArray, start + 88), 53) * k1);
|
||||
v.setLowValue(Long.rotateRight(y ^ k1, 49) * k1 + fetch64(byteArray, start));
|
||||
v.setHighValue(Long.rotateRight(v.getLowValue(), 42) * k1 + fetch64(byteArray, start + 8));
|
||||
w.setLowValue(Long.rotateRight(y + z, 35) * k1 + x);
|
||||
w.setHighValue(Long.rotateRight(x + fetch64(byteArray, start + 88), 53) * k1);
|
||||
|
||||
// This is the same inner loop as CityHash64(), manually unrolled.
|
||||
int pos = start;
|
||||
do {
|
||||
x = rotate64(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1;
|
||||
y = rotate64(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1;
|
||||
x = Long.rotateRight(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1;
|
||||
y = Long.rotateRight(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1;
|
||||
x ^= w.getHighValue();
|
||||
y += v.getLowValue() + fetch64(byteArray, pos + 40);
|
||||
z = rotate64(z + w.getLowValue(), 33) * k1;
|
||||
z = Long.rotateRight(z + w.getLowValue(), 33) * k1;
|
||||
v = weakHashLen32WithSeeds(byteArray, pos, v.getHighValue() * k1, x + w.getLowValue());
|
||||
w = weakHashLen32WithSeeds(byteArray, pos + 32, z + w.getHighValue(), y + fetch64(byteArray, pos + 16));
|
||||
|
||||
@ -251,11 +254,11 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
x = z;
|
||||
z = swapValue;
|
||||
pos += 64;
|
||||
x = rotate64(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1;
|
||||
y = rotate64(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1;
|
||||
x = Long.rotateRight(x + y + v.getLowValue() + fetch64(byteArray, pos + 8), 37) * k1;
|
||||
y = Long.rotateRight(y + v.getHighValue() + fetch64(byteArray, pos + 48), 42) * k1;
|
||||
x ^= w.getHighValue();
|
||||
y += v.getLowValue() + fetch64(byteArray, pos + 40);
|
||||
z = rotate64(z + w.getLowValue(), 33) * k1;
|
||||
z = Long.rotateRight(z + w.getLowValue(), 33) * k1;
|
||||
v = weakHashLen32WithSeeds(byteArray, pos, v.getHighValue() * k1, x + w.getLowValue());
|
||||
w = weakHashLen32WithSeeds(byteArray, pos + 32, z + w.getHighValue(), y + fetch64(byteArray, pos + 16));
|
||||
swapValue = x;
|
||||
@ -264,16 +267,16 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
pos += 64;
|
||||
len -= 128;
|
||||
} while (len >= 128);
|
||||
x += rotate64(v.getLowValue() + z, 49) * k0;
|
||||
y = y * k0 + rotate64(w.getHighValue(), 37);
|
||||
z = z * k0 + rotate64(w.getLowValue(), 27);
|
||||
x += Long.rotateRight(v.getLowValue() + z, 49) * k0;
|
||||
y = y * k0 + Long.rotateRight(w.getHighValue(), 37);
|
||||
z = z * k0 + Long.rotateRight(w.getLowValue(), 27);
|
||||
w.setLowValue(w.getLowValue() * 9);
|
||||
v.setLowValue(v.getLowValue() * k0);
|
||||
|
||||
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
||||
for (int tail_done = 0; tail_done < len; ) {
|
||||
tail_done += 32;
|
||||
y = rotate64(x + y, 42) * k0 + v.getHighValue();
|
||||
y = Long.rotateRight(x + y, 42) * k0 + v.getHighValue();
|
||||
w.setLowValue(w.getLowValue() + fetch64(byteArray, pos + len - tail_done + 16));
|
||||
x = x * k0 + w.getLowValue();
|
||||
z += w.getHighValue() + fetch64(byteArray, pos + len - tail_done);
|
||||
@ -333,8 +336,8 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
final long mul = k2 + len * 2L;
|
||||
final long a = fetch64(byteArray, 0) + k2;
|
||||
final long b = fetch64(byteArray, len - 8);
|
||||
final long c = rotate64(b, 37) * mul + a;
|
||||
final long d = (rotate64(a, 25) + b) * mul;
|
||||
final long c = Long.rotateRight(b, 37) * mul + a;
|
||||
final long d = (Long.rotateRight(a, 25) + b) * mul;
|
||||
return hashLen16(c, d, mul);
|
||||
}
|
||||
if (len >= 4) {
|
||||
@ -361,8 +364,8 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
final long b = fetch64(byteArray, 8);
|
||||
final long c = fetch64(byteArray, len - 8) * mul;
|
||||
final long d = fetch64(byteArray, len - 16) * k2;
|
||||
return hashLen16(rotate64(a + b, 43) + rotate64(c, 30) + d,
|
||||
a + rotate64(b + k2, 18) + c, mul);
|
||||
return hashLen16(Long.rotateRight(a + b, 43) + Long.rotateRight(c, 30) + d,
|
||||
a + Long.rotateRight(b + k2, 18) + c, mul);
|
||||
}
|
||||
|
||||
private long hashLen33to64(final byte[] byteArray) {
|
||||
@ -376,10 +379,10 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
final long f = fetch64(byteArray, 24) * 9;
|
||||
final long g = fetch64(byteArray, len - 8);
|
||||
final long h = fetch64(byteArray, len - 16) * mul;
|
||||
final long u = rotate64(a + g, 43) + (rotate64(b, 30) + c) * 9;
|
||||
final long u = Long.rotateRight(a + g, 43) + (Long.rotateRight(b, 30) + c) * 9;
|
||||
final long v = ((a + g) ^ d) + f + 1;
|
||||
final long w = Long.reverseBytes((u + v) * mul) + h;
|
||||
final long x = rotate64(e + f, 42) + c;
|
||||
final long x = Long.rotateRight(e + f, 42) + c;
|
||||
final long y = (Long.reverseBytes((v + w) * mul) + g) * mul;
|
||||
final long z = e + f + c;
|
||||
a = Long.reverseBytes((x + z) * mul + y) + b;
|
||||
@ -395,16 +398,6 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
return ByteUtil.bytesToInt(byteArray, start, ByteUtil.CPU_ENDIAN);
|
||||
}
|
||||
|
||||
private static long rotate64(final long val, final int shift) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >>> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
private static int rotate32(final int val, final int shift) {
|
||||
// Avoid shifting by 32: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >>> shift) | (val << (32 - shift)));
|
||||
}
|
||||
|
||||
private static long hashLen16(final long u, final long v, final long mul) {
|
||||
// Murmur-inspired hashing.
|
||||
long a = (u ^ v) * mul;
|
||||
@ -446,21 +439,21 @@ public class CityHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>
|
||||
private int mur(int a, int h) {
|
||||
// Helper from Murmur3 for combining two 32-bit values.
|
||||
a *= c1;
|
||||
a = rotate32(a, 17);
|
||||
a = Integer.rotateRight(a, 17);
|
||||
a *= c2;
|
||||
h ^= a;
|
||||
h = rotate32(h, 19);
|
||||
h = Integer.rotateRight(h, 19);
|
||||
return h * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
private static Number128 weakHashLen32WithSeeds(
|
||||
final long w, final long x, final long y, final long z, long a, long b) {
|
||||
a += w;
|
||||
b = rotate64(b + a + z, 21);
|
||||
b = Long.rotateRight(b + a + z, 21);
|
||||
final long c = a;
|
||||
a += x;
|
||||
a += y;
|
||||
b += rotate64(a, 44);
|
||||
b += Long.rotateRight(a, 44);
|
||||
return new Number128(a + z, b + c);
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@ import java.nio.charset.Charset;
|
||||
* @since 4.3.3
|
||||
*/
|
||||
public class MurmurHash implements Hash32<byte[]>, Hash64<byte[]>, Hash128<byte[]>{
|
||||
/**
|
||||
* 单例
|
||||
*/
|
||||
public static final MurmurHash INSTANCE = new MurmurHash();
|
||||
|
||||
// Constants for 32 bit variant
|
||||
|
@ -30,13 +30,7 @@ public abstract class AbstractMetroHash<R extends AbstractMetroHash<R>> implemen
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the instance's Metro hash function to the bytes in the given buffer.
|
||||
* This updates this instance's hashing state.
|
||||
*
|
||||
* @param input 内容
|
||||
* @return this
|
||||
*/
|
||||
@Override
|
||||
public R apply(final ByteBuffer input) {
|
||||
reset();
|
||||
while (input.remaining() >= 32) {
|
||||
@ -46,18 +40,32 @@ public abstract class AbstractMetroHash<R extends AbstractMetroHash<R>> implemen
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes a 32-byte chunk from the byte buffer and updates the hashing state.
|
||||
* 从byteBuffer中计算32-byte块并更新hash状态
|
||||
*
|
||||
* @param partialInput byte buffer with at least 32 bytes remaining.
|
||||
* @param partialInput byte buffer,至少有32byte的数据
|
||||
* @return this
|
||||
*/
|
||||
abstract R partialApply32ByteChunk(ByteBuffer partialInput);
|
||||
|
||||
/**
|
||||
* Consumes the remaining bytes from the byte buffer and updates the hashing state.
|
||||
* 从byteBuffer中计算剩余bytes并更新hash状态
|
||||
*
|
||||
* @param partialInput byte buffer with less than 32 bytes remaining.
|
||||
* @param partialInput byte buffer,少于32byte的数据
|
||||
* @return this
|
||||
*/
|
||||
abstract R partialApplyRemaining(ByteBuffer partialInput);
|
||||
|
||||
static long grab(final ByteBuffer bb, final int length) {
|
||||
long result = bb.get() & 0xFFL;
|
||||
for (int i = 1; i < length; i++) {
|
||||
result |= (bb.get() & 0xFFL) << (i << 3);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void writeLittleEndian(final long hash, final ByteBuffer output) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
output.put((byte) (hash >>> (i*8)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ public interface MetroHash<R extends MetroHash<R>> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the instance's Metro hash function to the bytes in the given buffer.
|
||||
* This updates this instance's hashing state.
|
||||
* 将给定的{@link ByteBuffer}中的数据追加计算hash值<br>
|
||||
* 此方法会更新hash值状态
|
||||
*
|
||||
* @param input 内容
|
||||
* @return this
|
||||
@ -38,8 +38,7 @@ public interface MetroHash<R extends MetroHash<R>> {
|
||||
R apply(final ByteBuffer input);
|
||||
|
||||
/**
|
||||
* Writes the current hash to the given byte buffer in big-endian order.
|
||||
* 将结果hash值写出到{@link ByteBuffer}中
|
||||
* 将结果hash值写出到{@link ByteBuffer}中,可选端序
|
||||
*
|
||||
* @param output 输出
|
||||
* @param byteOrder 端序
|
||||
|
@ -52,24 +52,6 @@ public class MetroHash128 extends AbstractMetroHash<MetroHash128> implements Has
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取高64位结果hash值
|
||||
*
|
||||
* @return hash值
|
||||
*/
|
||||
public long getHigh() {
|
||||
return v0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取低64位结果hash值
|
||||
*
|
||||
* @return hash值
|
||||
*/
|
||||
public long getLow() {
|
||||
return v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结果hash值
|
||||
*
|
||||
@ -87,8 +69,8 @@ public class MetroHash128 extends AbstractMetroHash<MetroHash128> implements Has
|
||||
@Override
|
||||
public MetroHash128 write(final ByteBuffer output, final ByteOrder byteOrder) {
|
||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||
MetroHashInternalUtil.writeLittleEndian(v0, output);
|
||||
MetroHashInternalUtil.writeLittleEndian(v1, output);
|
||||
writeLittleEndian(v0, output);
|
||||
writeLittleEndian(v1, output);
|
||||
} else {
|
||||
output.asLongBuffer().put(v1).put(v0);
|
||||
}
|
||||
@ -98,14 +80,14 @@ public class MetroHash128 extends AbstractMetroHash<MetroHash128> implements Has
|
||||
@Override
|
||||
MetroHash128 partialApply32ByteChunk(final ByteBuffer partialInput) {
|
||||
assert partialInput.remaining() >= 32;
|
||||
v0 += MetroHashInternalUtil.grab8(partialInput) * K0;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2;
|
||||
v1 += MetroHashInternalUtil.grab8(partialInput) * K1;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3;
|
||||
v2 += MetroHashInternalUtil.grab8(partialInput) * K2;
|
||||
v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0;
|
||||
v3 += MetroHashInternalUtil.grab8(partialInput) * K3;
|
||||
v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1;
|
||||
v0 += grab(partialInput, 8) * K0;
|
||||
v0 = Long.rotateRight(v0, 29) + v2;
|
||||
v1 += grab(partialInput, 8) * K1;
|
||||
v1 = Long.rotateRight(v1, 29) + v3;
|
||||
v2 += grab(partialInput, 8) * K2;
|
||||
v2 = Long.rotateRight(v2, 29) + v0;
|
||||
v3 += grab(partialInput, 8) * K3;
|
||||
v3 = Long.rotateRight(v3, 29) + v1;
|
||||
++nChunks;
|
||||
return this;
|
||||
}
|
||||
@ -131,52 +113,52 @@ public class MetroHash128 extends AbstractMetroHash<MetroHash128> implements Has
|
||||
if (partialInput.remaining() >= 1) {
|
||||
metroHash128_1(partialInput);
|
||||
}
|
||||
v0 += MetroHashInternalUtil.rotateRight64(v0 * K0 + v1, 13);
|
||||
v1 += MetroHashInternalUtil.rotateRight64(v1 * K1 + v0, 37);
|
||||
v0 += MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 13);
|
||||
v1 += MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 37);
|
||||
v0 += Long.rotateRight(v0 * K0 + v1, 13);
|
||||
v1 += Long.rotateRight(v1 * K1 + v0, 37);
|
||||
v0 += Long.rotateRight(v0 * K2 + v1, 13);
|
||||
v1 += Long.rotateRight(v1 * K3 + v0, 37);
|
||||
return this;
|
||||
}
|
||||
|
||||
// region ----- private methods
|
||||
private void metroHash128_32() {
|
||||
v2 ^= MetroHashInternalUtil.rotateRight64((v0 + v3) * K0 + v1, 21) * K1;
|
||||
v3 ^= MetroHashInternalUtil.rotateRight64((v1 + v2) * K1 + v0, 21) * K0;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64((v0 + v2) * K0 + v3, 21) * K1;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64((v1 + v3) * K1 + v2, 21) * K0;
|
||||
v2 ^= Long.rotateRight((v0 + v3) * K0 + v1, 21) * K1;
|
||||
v3 ^= Long.rotateRight((v1 + v2) * K1 + v0, 21) * K0;
|
||||
v0 ^= Long.rotateRight((v0 + v2) * K0 + v3, 21) * K1;
|
||||
v1 ^= Long.rotateRight((v1 + v3) * K1 + v2, 21) * K0;
|
||||
}
|
||||
|
||||
private void metroHash128_16(final ByteBuffer bb) {
|
||||
v0 += MetroHashInternalUtil.grab8(bb) * K2;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
|
||||
v1 += MetroHashInternalUtil.grab8(bb) * K2;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 45) * K1;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 45) * K0;
|
||||
v0 += grab(bb, 8) * K2;
|
||||
v0 = Long.rotateRight(v0, 33) * K3;
|
||||
v1 += grab(bb, 8) * K2;
|
||||
v1 = Long.rotateRight(v1, 33) * K3;
|
||||
v0 ^= Long.rotateRight(v0 * K2 + v1, 45) * K1;
|
||||
v1 ^= Long.rotateRight(v1 * K3 + v0, 45) * K0;
|
||||
}
|
||||
|
||||
private void metroHash128_8(final ByteBuffer bb) {
|
||||
v0 += MetroHashInternalUtil.grab8(bb) * K2;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 27) * K1;
|
||||
v0 += grab(bb, 8) * K2;
|
||||
v0 = Long.rotateRight(v0, 33) * K3;
|
||||
v0 ^= Long.rotateRight(v0 * K2 + v1, 27) * K1;
|
||||
}
|
||||
|
||||
private void metroHash128_4(final ByteBuffer bb) {
|
||||
v1 += MetroHashInternalUtil.grab4(bb) * K2;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 46) * K0;
|
||||
v1 += grab(bb, 4) * K2;
|
||||
v1 = Long.rotateRight(v1, 33) * K3;
|
||||
v1 ^= Long.rotateRight(v1 * K3 + v0, 46) * K0;
|
||||
}
|
||||
|
||||
private void metroHash128_2(final ByteBuffer bb) {
|
||||
v0 += MetroHashInternalUtil.grab2(bb) * K2;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 33) * K3;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K2 + v1, 22) * K1;
|
||||
v0 += grab(bb, 2) * K2;
|
||||
v0 = Long.rotateRight(v0, 33) * K3;
|
||||
v0 ^= Long.rotateRight(v0 * K2 + v1, 22) * K1;
|
||||
}
|
||||
|
||||
private void metroHash128_1(final ByteBuffer bb) {
|
||||
v1 += MetroHashInternalUtil.grab1(bb) * K2;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 33) * K3;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3 + v0, 58) * K0;
|
||||
v1 += grab(bb, 1) * K2;
|
||||
v1 = Long.rotateRight(v1, 33) * K3;
|
||||
v1 ^= Long.rotateRight(v1 * K3 + v0, 58) * K0;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class MetroHash64 extends AbstractMetroHash<MetroHash64> implements Hash6
|
||||
@Override
|
||||
public MetroHash64 write(final ByteBuffer output, final ByteOrder byteOrder) {
|
||||
if(ByteOrder.LITTLE_ENDIAN == byteOrder){
|
||||
MetroHashInternalUtil.writeLittleEndian(hash, output);
|
||||
writeLittleEndian(hash, output);
|
||||
} else{
|
||||
output.asLongBuffer().put(hash);
|
||||
}
|
||||
@ -77,14 +77,14 @@ public class MetroHash64 extends AbstractMetroHash<MetroHash64> implements Hash6
|
||||
@Override
|
||||
MetroHash64 partialApply32ByteChunk(final ByteBuffer partialInput) {
|
||||
assert partialInput.remaining() >= 32;
|
||||
v0 += MetroHashInternalUtil.grab8(partialInput) * K0;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) + v2;
|
||||
v1 += MetroHashInternalUtil.grab8(partialInput) * K1;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) + v3;
|
||||
v2 += MetroHashInternalUtil.grab8(partialInput) * K2;
|
||||
v2 = MetroHashInternalUtil.rotateRight64(v2, 29) + v0;
|
||||
v3 += MetroHashInternalUtil.grab8(partialInput) * K3;
|
||||
v3 = MetroHashInternalUtil.rotateRight64(v3, 29) + v1;
|
||||
v0 += grab(partialInput, 8) * K0;
|
||||
v0 = Long.rotateRight(v0, 29) + v2;
|
||||
v1 += grab(partialInput, 8) * K1;
|
||||
v1 = Long.rotateRight(v1, 29) + v3;
|
||||
v2 += grab(partialInput, 8) * K2;
|
||||
v2 = Long.rotateRight(v2, 29) + v0;
|
||||
v3 += grab(partialInput, 8) * K3;
|
||||
v3 = Long.rotateRight(v3, 29) + v1;
|
||||
++nChunks;
|
||||
return this;
|
||||
}
|
||||
@ -110,49 +110,49 @@ public class MetroHash64 extends AbstractMetroHash<MetroHash64> implements Hash6
|
||||
if (partialInput.remaining() >= 1) {
|
||||
metroHash64_1(partialInput);
|
||||
}
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 28);
|
||||
hash ^= Long.rotateRight(hash, 28);
|
||||
hash *= K0;
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 29);
|
||||
hash ^= Long.rotateRight(hash, 29);
|
||||
return this;
|
||||
}
|
||||
|
||||
// region ----- private methods
|
||||
private void metroHash64_32() {
|
||||
v2 ^= MetroHashInternalUtil.rotateRight64(((v0 + v3) * K0) + v1, 37) * K1;
|
||||
v3 ^= MetroHashInternalUtil.rotateRight64(((v1 + v2) * K1) + v0, 37) * K0;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64(((v0 + v2) * K0) + v3, 37) * K1;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64(((v1 + v3) * K1) + v2, 37) * K0;
|
||||
v2 ^= Long.rotateRight(((v0 + v3) * K0) + v1, 37) * K1;
|
||||
v3 ^= Long.rotateRight(((v1 + v2) * K1) + v0, 37) * K0;
|
||||
v0 ^= Long.rotateRight(((v0 + v2) * K0) + v3, 37) * K1;
|
||||
v1 ^= Long.rotateRight(((v1 + v3) * K1) + v2, 37) * K0;
|
||||
hash += v0 ^ v1;
|
||||
}
|
||||
|
||||
private void metroHash64_16(final ByteBuffer bb) {
|
||||
v0 = hash + MetroHashInternalUtil.grab8(bb) * K2;
|
||||
v0 = MetroHashInternalUtil.rotateRight64(v0, 29) * K3;
|
||||
v1 = hash + MetroHashInternalUtil.grab8(bb) * K2;
|
||||
v1 = MetroHashInternalUtil.rotateRight64(v1, 29) * K3;
|
||||
v0 ^= MetroHashInternalUtil.rotateRight64(v0 * K0, 21) + v1;
|
||||
v1 ^= MetroHashInternalUtil.rotateRight64(v1 * K3, 21) + v0;
|
||||
v0 = hash + grab(bb, 8) * K2;
|
||||
v0 = Long.rotateRight(v0, 29) * K3;
|
||||
v1 = hash + grab(bb, 8) * K2;
|
||||
v1 = Long.rotateRight(v1, 29) * K3;
|
||||
v0 ^= Long.rotateRight(v0 * K0, 21) + v1;
|
||||
v1 ^= Long.rotateRight(v1 * K3, 21) + v0;
|
||||
hash += v1;
|
||||
}
|
||||
|
||||
private void metroHash64_8(final ByteBuffer bb) {
|
||||
hash += MetroHashInternalUtil.grab8(bb) * K3;
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 55) * K1;
|
||||
hash += grab(bb, 8) * K3;
|
||||
hash ^= Long.rotateRight(hash, 55) * K1;
|
||||
}
|
||||
|
||||
private void metroHash64_4(final ByteBuffer bb) {
|
||||
hash += MetroHashInternalUtil.grab4(bb) * K3;
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 26) * K1;
|
||||
hash += grab(bb, 4) * K3;
|
||||
hash ^= Long.rotateRight(hash, 26) * K1;
|
||||
}
|
||||
|
||||
private void metroHash64_2(final ByteBuffer bb) {
|
||||
hash += MetroHashInternalUtil.grab2(bb) * K3;
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 48) * K1;
|
||||
hash += grab(bb, 2) * K3;
|
||||
hash ^= Long.rotateRight(hash, 48) * K1;
|
||||
}
|
||||
|
||||
private void metroHash64_1(final ByteBuffer bb) {
|
||||
hash += MetroHashInternalUtil.grab1(bb) * K3;
|
||||
hash ^= MetroHashInternalUtil.rotateRight64(hash, 37) * K1;
|
||||
hash += grab(bb, 1) * K3;
|
||||
hash ^= Long.rotateRight(hash, 37) * K1;
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
package cn.hutool.core.codec.hash.metro;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
class MetroHashInternalUtil {
|
||||
|
||||
static void writeLittleEndian(final long hash, final ByteBuffer output) {
|
||||
output.put((byte) hash);
|
||||
output.put((byte) (hash >>> 8));
|
||||
output.put((byte) (hash >>> 16));
|
||||
output.put((byte) (hash >>> 24));
|
||||
output.put((byte) (hash >>> 32));
|
||||
output.put((byte) (hash >>> 40));
|
||||
output.put((byte) (hash >>> 48));
|
||||
output.put((byte) (hash >>> 56));
|
||||
}
|
||||
|
||||
static long rotateRight64(final long x, final int r) {
|
||||
return (x >>> r) | (x << (64 - r));
|
||||
}
|
||||
|
||||
static long grab1(final ByteBuffer bb) {
|
||||
return ((long) bb.get() & 0xFFL);
|
||||
}
|
||||
|
||||
static long grab2(final ByteBuffer bb) {
|
||||
final long v0 = bb.get();
|
||||
final long v1 = bb.get();
|
||||
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8;
|
||||
}
|
||||
|
||||
static long grab4(final ByteBuffer bb) {
|
||||
final long v0 = bb.get();
|
||||
final long v1 = bb.get();
|
||||
final long v2 = bb.get();
|
||||
final long v3 = bb.get();
|
||||
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24;
|
||||
}
|
||||
|
||||
static long grab8(final ByteBuffer bb) {
|
||||
final long v0 = bb.get();
|
||||
final long v1 = bb.get();
|
||||
final long v2 = bb.get();
|
||||
final long v3 = bb.get();
|
||||
final long v4 = bb.get();
|
||||
final long v5 = bb.get();
|
||||
final long v6 = bb.get();
|
||||
final long v7 = bb.get();
|
||||
return (v0 & 0xFFL) | (v1 & 0xFFL) << 8 | (v2 & 0xFFL) << 16 | (v3 & 0xFFL) << 24 | (v4 & 0xFFL) << 32 | (v5 & 0xFFL) << 40 | (v6 & 0xFFL) << 48 | (v7 & 0xFFL) << 56;
|
||||
}
|
||||
}
|
@ -1761,5 +1761,4 @@ public class NumberUtil {
|
||||
public static boolean isEven(final int num) {
|
||||
return false == isOdd(num);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,10 +30,13 @@ import java.util.function.Predicate;
|
||||
* 也可以将已有的树转换为集合,例如:
|
||||
* <pre>{@code final List<JavaBean> javaBeanList = beanTree.flat(originJavaBeanTree);}</pre>
|
||||
*
|
||||
* <p>最后,引用一句电影经典台词: 无处安放的双手,以及无处安放的灵魂。——《Hello!树先生》</p>
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param <R> 主键、外键类型
|
||||
* @author VampireAchao
|
||||
* @author emptypoint
|
||||
* @author CreateSequence
|
||||
* 最后,引用一句电影经典台词: 无处安放的双手,以及无处安放的灵魂。——《Hello!树先生》
|
||||
*/
|
||||
public class BeanTree<T, R extends Comparable<R>> {
|
||||
|
||||
@ -126,10 +129,10 @@ public class BeanTree<T, R extends Comparable<R>> {
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return ListUtil.zero();
|
||||
}
|
||||
if (Objects.isNull(parentPredicate)) {
|
||||
final Map<R, List<T>> pIdValuesMap = EasyStream.of(list)
|
||||
.peek(e -> Objects.requireNonNull(idGetter.apply(e), () -> "The id of tree node must not be null " + e))
|
||||
.group(pidGetter);
|
||||
if (Objects.isNull(parentPredicate)) {
|
||||
final Map<R, List<T>> pIdValuesMap = EasyStream.of(list)
|
||||
.peek(e -> Objects.requireNonNull(idGetter.apply(e), () -> "The id of tree node must not be null " + e))
|
||||
.group(pidGetter);
|
||||
final List<T> parents = pIdValuesMap.getOrDefault(pidValue, new ArrayList<>());
|
||||
findChildren(list, pIdValuesMap);
|
||||
return parents;
|
||||
@ -206,7 +209,7 @@ public class BeanTree<T, R extends Comparable<R>> {
|
||||
* @param pIdValuesMap 父id与子集的映射
|
||||
*/
|
||||
private void findChildren(final List<T> list, final Map<R, List<T>> pIdValuesMap) {
|
||||
for (T node : list) {
|
||||
for (final T node : list) {
|
||||
final List<T> children = pIdValuesMap.get(idGetter.apply(node));
|
||||
if (children != null) {
|
||||
childrenSetter.accept(node, children);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.hutool.core.codec.hash.metro;
|
||||
|
||||
import cn.hutool.core.codec.HexUtil;
|
||||
import cn.hutool.core.codec.Number128;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@ -106,7 +107,8 @@ public class MetroHash128Test {
|
||||
|
||||
static String h128(final String input) {
|
||||
final MetroHash128 mh = MetroHash128.of(0).apply(ByteBuffer.wrap(StrUtil.utf8Bytes(input)));
|
||||
return hex(mh.getHigh()) + hex(mh.getLow());
|
||||
final Number128 hash = mh.get();
|
||||
return hex(hash.getHighValue()) + hex(hash.getLowValue());
|
||||
}
|
||||
|
||||
private static String hex(final long value){
|
||||
|
@ -82,13 +82,13 @@ public class NumberUtilTest {
|
||||
|
||||
@Test
|
||||
public void isIntegerTest() {
|
||||
String[] validNumArr = {"0", "-0", "+0", "12", "+12", "1234567890", "2147483647", "-2147483648",
|
||||
final String[] validNumArr = {"0", "-0", "+0", "12", "+12", "1234567890", "2147483647", "-2147483648",
|
||||
"0x012345678", "0X012345678", "0xabcdef", "-0xabcdef", "0x12abcdef", "0x7FFFFFFF", "-0x80000000",
|
||||
"01234567", "017777777777", "-020000000000"
|
||||
};
|
||||
privateIsIntegerTest(validNumArr, true);
|
||||
|
||||
String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99L", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3",
|
||||
final String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99L", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3",
|
||||
"2147483648", "0x80000000", "020000000000", "-2147483649", "-0x80000001", "-020000000001", "-020000000001",
|
||||
"a", "+a", "123abc", "09"
|
||||
};
|
||||
@ -96,14 +96,14 @@ public class NumberUtilTest {
|
||||
}
|
||||
|
||||
private void privateIsIntegerTest(final String[] numStrArr, final boolean expected) {
|
||||
for (String numStr : numStrArr) {
|
||||
for (final String numStr : numStrArr) {
|
||||
Assert.assertEquals("未通过的数字为: " + numStr, expected, NumberUtil.isInteger(numStr));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLongTest() {
|
||||
String[] validNumArr = {
|
||||
final String[] validNumArr = {
|
||||
"0", "0L", "-0L", "+0L", "12", "+12", "1234567890123456789", "99L",
|
||||
"2147483648", "0x80000000", "020000000000", "-2147483649", "-0x80000001", "-020000000001", "-020000000001",
|
||||
"9223372036854775807", "-9223372036854775808",
|
||||
@ -113,7 +113,7 @@ public class NumberUtilTest {
|
||||
};
|
||||
privateIsLongTest(validNumArr, true);
|
||||
|
||||
String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3",
|
||||
final String[] invalidNumArr = {null, "", " ", "+", "+1.", ".1", "99D", "99F", "12.3", "123e1", "-12.3", "1.2.3",
|
||||
"a", "+a", "123abc", "09",
|
||||
"9223372036854775808", "-9223372036854775809",
|
||||
"0x8000000000000000", "-0x8000000000000001",
|
||||
@ -123,7 +123,7 @@ public class NumberUtilTest {
|
||||
}
|
||||
|
||||
private void privateIsLongTest(final String[] numStrArr, final boolean expected) {
|
||||
for (String numStr : numStrArr) {
|
||||
for (final String numStr : numStrArr) {
|
||||
Assert.assertEquals("未通过的数字为: " + numStr, expected, NumberUtil.isLong(numStr));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user