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