|
19 | 19 | import static com.google.common.base.Preconditions.checkArgument;
|
20 | 20 | import static com.google.common.base.Preconditions.checkNotNull;
|
21 | 21 |
|
22 |
| -import java.nio.ByteOrder; |
23 |
| -import java.util.Comparator; |
24 |
| - |
25 |
| -import sun.misc.Unsafe; |
26 | 22 |
|
27 | 23 | /**
|
28 | 24 | * Static utility methods pertaining to {@code byte} primitives that interpret
|
@@ -245,185 +241,5 @@ public static String join(String separator, byte... array) {
|
245 | 241 | return builder.toString();
|
246 | 242 | }
|
247 | 243 |
|
248 |
| - /** |
249 |
| - * Returns a comparator that compares two {@code byte} arrays |
250 |
| - * lexicographically. That is, it compares, using {@link |
251 |
| - * #compare(byte, byte)}), the first pair of values that follow any common |
252 |
| - * prefix, or when one array is a prefix of the other, treats the shorter |
253 |
| - * array as the lesser. For example, {@code [] < [0x01] < [0x01, 0x7F] < |
254 |
| - * [0x01, 0x80] < [0x02]}. Values are treated as unsigned. |
255 |
| - * |
256 |
| - * <p>The returned comparator is inconsistent with {@link |
257 |
| - * Object#equals(Object)} (since arrays support only identity equality), but |
258 |
| - * it is consistent with {@link java.util.Arrays#equals(byte[], byte[])}. |
259 |
| - * |
260 |
| - * @see <a href="http://en.wikipedia.org/wiki/Lexicographical_order"> |
261 |
| - * Lexicographical order article at Wikipedia</a> |
262 |
| - * @since 2.0 |
263 |
| - */ |
264 |
| - public static Comparator<byte[]> lexicographicalComparator() { |
265 |
| - return LexicographicalComparatorHolder.BEST_COMPARATOR; |
266 |
| - } |
267 |
| - |
268 |
| - static Comparator<byte[]> lexicographicalComparatorJavaImpl() { |
269 |
| - return LexicographicalComparatorHolder.PureJavaComparator.INSTANCE; |
270 |
| - } |
271 |
| - |
272 |
| - /** |
273 |
| - * Provides a lexicographical comparator implementation; either a Java |
274 |
| - * implementation or a faster implementation based on {@link Unsafe}. |
275 |
| - * |
276 |
| - * <p>Uses reflection to gracefully fall back to the Java implementation if |
277 |
| - * {@code Unsafe} isn't available. |
278 |
| - */ |
279 |
| - static class LexicographicalComparatorHolder { |
280 |
| - static final String UNSAFE_COMPARATOR_NAME = |
281 |
| - LexicographicalComparatorHolder.class.getName() + "$UnsafeComparator"; |
282 |
| - |
283 |
| - static final Comparator<byte[]> BEST_COMPARATOR = getBestComparator(); |
284 |
| - |
285 |
| - enum UnsafeComparator implements Comparator<byte[]> { |
286 |
| - INSTANCE; |
287 |
| - |
288 |
| - static final boolean BIG_ENDIAN = |
289 |
| - ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); |
290 |
| - |
291 |
| - /* |
292 |
| - * The following static final fields exist for performance reasons. |
293 |
| - * |
294 |
| - * In UnsignedBytesBenchmark, accessing the following objects via static |
295 |
| - * final fields is the fastest (more than twice as fast as the Java |
296 |
| - * implementation, vs ~1.5x with non-final static fields, on x86_32) |
297 |
| - * under the Hotspot server compiler. The reason is obviously that the |
298 |
| - * non-final fields need to be reloaded inside the loop. |
299 |
| - * |
300 |
| - * And, no, defining (final or not) local variables out of the loop still |
301 |
| - * isn't as good because the null check on the theUnsafe object remains |
302 |
| - * inside the loop and BYTE_ARRAY_BASE_OFFSET doesn't get |
303 |
| - * constant-folded. |
304 |
| - * |
305 |
| - * The compiler can treat static final fields as compile-time constants |
306 |
| - * and can constant-fold them while (final or not) local variables are |
307 |
| - * run time values. |
308 |
| - */ |
309 |
| - |
310 |
| - static final Unsafe theUnsafe; |
311 |
| - |
312 |
| - /** The offset to the first element in a byte array. */ |
313 |
| - static final int BYTE_ARRAY_BASE_OFFSET; |
314 |
| - |
315 |
| - static { |
316 |
| - theUnsafe = getUnsafe(); |
317 | 244 |
|
318 |
| - BYTE_ARRAY_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class); |
319 |
| - |
320 |
| - // sanity check - this should never fail |
321 |
| - if (theUnsafe.arrayIndexScale(byte[].class) != 1) { |
322 |
| - throw new AssertionError(); |
323 |
| - } |
324 |
| - } |
325 |
| - |
326 |
| - /** |
327 |
| - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. |
328 |
| - * Replace with a simple call to Unsafe.getUnsafe when integrating |
329 |
| - * into a jdk. |
330 |
| - * |
331 |
| - * @return a sun.misc.Unsafe |
332 |
| - */ |
333 |
| - private static sun.misc.Unsafe getUnsafe() { |
334 |
| - try { |
335 |
| - return sun.misc.Unsafe.getUnsafe(); |
336 |
| - } catch (SecurityException tryReflectionInstead) {} |
337 |
| - try { |
338 |
| - return java.security.AccessController.doPrivileged |
339 |
| - (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() { |
340 |
| - public sun.misc.Unsafe run() throws Exception { |
341 |
| - Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class; |
342 |
| - for (java.lang.reflect.Field f : k.getDeclaredFields()) { |
343 |
| - f.setAccessible(true); |
344 |
| - Object x = f.get(null); |
345 |
| - if (k.isInstance(x)) |
346 |
| - return k.cast(x); |
347 |
| - } |
348 |
| - throw new NoSuchFieldError("the Unsafe"); |
349 |
| - }}); |
350 |
| - } catch (java.security.PrivilegedActionException e) { |
351 |
| - throw new RuntimeException("Could not initialize intrinsics", |
352 |
| - e.getCause()); |
353 |
| - } |
354 |
| - } |
355 |
| - |
356 |
| - @Override public int compare(byte[] left, byte[] right) { |
357 |
| - int minLength = Math.min(left.length, right.length); |
358 |
| - int minWords = minLength / Longs.BYTES; |
359 |
| - |
360 |
| - /* |
361 |
| - * Compare 8 bytes at a time. Benchmarking shows comparing 8 bytes at a |
362 |
| - * time is no slower than comparing 4 bytes at a time even on 32-bit. |
363 |
| - * On the other hand, it is substantially faster on 64-bit. |
364 |
| - */ |
365 |
| - for (int i = 0; i < minWords * Longs.BYTES; i += Longs.BYTES) { |
366 |
| - long lw = theUnsafe.getLong(left, BYTE_ARRAY_BASE_OFFSET + (long) i); |
367 |
| - long rw = theUnsafe.getLong(right, BYTE_ARRAY_BASE_OFFSET + (long) i); |
368 |
| - if (lw != rw) { |
369 |
| - if (BIG_ENDIAN) { |
370 |
| - return UnsignedLongs.compare(lw, rw); |
371 |
| - } |
372 |
| - |
373 |
| - /* |
374 |
| - * We want to compare only the first index where left[index] != right[index]. |
375 |
| - * This corresponds to the least significant nonzero byte in lw ^ rw, since lw |
376 |
| - * and rw are little-endian. Long.numberOfTrailingZeros(diff) tells us the least |
377 |
| - * significant nonzero bit, and zeroing out the first three bits of L.nTZ gives us the |
378 |
| - * shift to get that least significant nonzero byte. |
379 |
| - */ |
380 |
| - int n = Long.numberOfTrailingZeros(lw ^ rw) & ~0x7; |
381 |
| - return (int) (((lw >>> n) & UNSIGNED_MASK) - ((rw >>> n) & UNSIGNED_MASK)); |
382 |
| - } |
383 |
| - } |
384 |
| - |
385 |
| - // The epilogue to cover the last (minLength % 8) elements. |
386 |
| - for (int i = minWords * Longs.BYTES; i < minLength; i++) { |
387 |
| - int result = UnsignedBytes.compare(left[i], right[i]); |
388 |
| - if (result != 0) { |
389 |
| - return result; |
390 |
| - } |
391 |
| - } |
392 |
| - return left.length - right.length; |
393 |
| - } |
394 |
| - } |
395 |
| - |
396 |
| - enum PureJavaComparator implements Comparator<byte[]> { |
397 |
| - INSTANCE; |
398 |
| - |
399 |
| - @Override public int compare(byte[] left, byte[] right) { |
400 |
| - int minLength = Math.min(left.length, right.length); |
401 |
| - for (int i = 0; i < minLength; i++) { |
402 |
| - int result = UnsignedBytes.compare(left[i], right[i]); |
403 |
| - if (result != 0) { |
404 |
| - return result; |
405 |
| - } |
406 |
| - } |
407 |
| - return left.length - right.length; |
408 |
| - } |
409 |
| - } |
410 |
| - |
411 |
| - /** |
412 |
| - * Returns the Unsafe-using Comparator, or falls back to the pure-Java |
413 |
| - * implementation if unable to do so. |
414 |
| - */ |
415 |
| - static Comparator<byte[]> getBestComparator() { |
416 |
| - try { |
417 |
| - Class<?> theClass = Class.forName(UNSAFE_COMPARATOR_NAME); |
418 |
| - |
419 |
| - // yes, UnsafeComparator does implement Comparator<byte[]> |
420 |
| - @SuppressWarnings("unchecked") |
421 |
| - Comparator<byte[]> comparator = |
422 |
| - (Comparator<byte[]>) theClass.getEnumConstants()[0]; |
423 |
| - return comparator; |
424 |
| - } catch (Throwable t) { // ensure we really catch *everything* |
425 |
| - return lexicographicalComparatorJavaImpl(); |
426 |
| - } |
427 |
| - } |
428 |
| - } |
429 | 245 | }
|
0 commit comments