src/share/classes/java/util/UUID.java

Print this page
rev 6516 : 8007398: Peformance improvements to Integer and Long string formatting.
Contributed-by: Steven Schlansker <stevenschlansker@gmail.com>

*** 25,34 **** --- 25,37 ---- package java.util; import java.security.*; + import sun.misc.JavaLangAccess; + import sun.misc.SharedSecrets; + /** * A class that represents an immutable universally unique identifier (UUID). * A UUID represents a 128-bit value. * * <p> There exist different variants of these global identifiers. The methods
*** 72,81 **** --- 75,90 ---- /** * Explicit serialVersionUID for interoperability. */ private static final long serialVersionUID = -4856846361193249489L; + /** + * Provides access to String's non-public constructor that does not copy the char[] + */ + private static final JavaLangAccess JAVA_LANG_ACCESS + = SharedSecrets.getJavaLangAccess(); + /* * The most significant 64 bits of this UUID. * * @serial */
*** 176,215 **** /** * Creates a {@code UUID} from the string standard representation as * described in the {@link #toString} method. * ! * @param name * A string that specifies a {@code UUID} * * @return A {@code UUID} with the specified value * * @throws IllegalArgumentException * If name does not conform to the string representation as * described in {@link #toString} * */ ! public static UUID fromString(String name) { ! String[] components = name.split("-"); ! if (components.length != 5) ! throw new IllegalArgumentException("Invalid UUID string: "+name); ! for (int i=0; i<5; i++) ! components[i] = "0x"+components[i]; ! long mostSigBits = Long.decode(components[0]).longValue(); mostSigBits <<= 16; ! mostSigBits |= Long.decode(components[1]).longValue(); mostSigBits <<= 16; ! mostSigBits |= Long.decode(components[2]).longValue(); ! long leastSigBits = Long.decode(components[3]).longValue(); leastSigBits <<= 48; ! leastSigBits |= Long.decode(components[4]).longValue(); return new UUID(mostSigBits, leastSigBits); } // Field Accessor Methods /** * Returns the least significant 64 bits of this UUID's 128 bit value. * --- 185,292 ---- /** * Creates a {@code UUID} from the string standard representation as * described in the {@link #toString} method. * ! * @param str * A string that specifies a {@code UUID} * * @return A {@code UUID} with the specified value * * @throws IllegalArgumentException * If name does not conform to the string representation as * described in {@link #toString} * */ ! public static UUID fromString(String str) { ! int dashCount = 4; ! int [] dashPos = new int [6]; ! dashPos[0] = -1; ! dashPos[5] = str.length(); ! for (int i = str.length()-1; i >= 0; i--) { ! if (str.charAt(i) == '-') { ! if (dashCount == 0) { ! throw new IllegalArgumentException("Invalid UUID string: " + str); ! } ! dashPos[dashCount--] = i; ! } ! } ! ! if (dashCount > 0) { ! throw new IllegalArgumentException("Invalid UUID string: " + str); ! } ! ! long mostSigBits = decode(str, dashPos, 0) & 0xffffffffL; mostSigBits <<= 16; ! mostSigBits |= decode(str, dashPos, 1) & 0xffffL; mostSigBits <<= 16; ! mostSigBits |= decode(str, dashPos, 2) & 0xffffL; ! long leastSigBits = decode(str, dashPos, 3) & 0xffffL; leastSigBits <<= 48; ! leastSigBits |= decode(str, dashPos, 4) & 0xffffffffffffL; return new UUID(mostSigBits, leastSigBits); } + private static long decode(final String str, final int [] dashPos, final int field) { + int start = dashPos[field]+1; + int end = dashPos[field+1]; + if (start >= end) { + throw new IllegalArgumentException("Invalid UUID string: " + str); + } + return decodeLongHexString(str, start, end); + } + + private static final int NUM_ALPHA_DIFF = 'A' - '9' - 1; + private static final int LOWER_UPPER_DIFF = 'a' - 'A'; + + /** + * Given a hexadecimal string, decode a portion into a long. + * @param str the string to decode + * @param start the start of the substring to decode + * @param end the end of the substring to decode + */ + public static long decodeLongHexString(CharSequence str, int start, int end) + { + long curr = 0; + for (int i = start; i < end; i++) { + int x = getNibbleFromHexChar(str.charAt(i)); + curr <<= 4; + if (curr < 0) { + throw new NumberFormatException("long overflow"); + } + curr |= x; + } + return curr; + } + + /** + * Given a hexadecimal digit, return the decimal value. + * @param c the character to decode + */ + public static int getNibbleFromHexChar(final char c) + { + int x = c - '0'; + if (x > 9) { + x -= NUM_ALPHA_DIFF; // difference between '9' and 'A' + if (x > 15) { + x -= LOWER_UPPER_DIFF; // difference between 'a' and 'A' + } + if (x < 10) { + throw new IllegalArgumentException(c + " is not a valid character for a hex string"); + } + } + + if (x < 0 || x > 15) { + throw new IllegalArgumentException(c + " is not a valid character for a hex string"); + } + + return x; + } + // Field Accessor Methods /** * Returns the least significant 64 bits of this UUID's 128 bit value. *
*** 369,390 **** * | "A" | "B" | "C" | "D" | "E" | "F" * }</pre></blockquote> * * @return A string representation of this {@code UUID} */ ! public String toString() { ! return (digits(mostSigBits >> 32, 8) + "-" + ! digits(mostSigBits >> 16, 4) + "-" + ! digits(mostSigBits, 4) + "-" + ! digits(leastSigBits >> 48, 4) + "-" + ! digits(leastSigBits, 12)); } ! /** Returns val represented by the specified number of hex digits. */ ! private static String digits(long val, int digits) { ! long hi = 1L << (digits * 4); ! return Long.toHexString(hi | (val & (hi - 1))).substring(1); } /** * Returns a hash code for this {@code UUID}. * --- 446,486 ---- * | "A" | "B" | "C" | "D" | "E" | "F" * }</pre></blockquote> * * @return A string representation of this {@code UUID} */ ! public String toString() ! { ! return toString(getMostSignificantBits(), getLeastSignificantBits()); ! } ! ! /** ! * Returns a {@code String} object representing a UUID passed in as ! * two longs. Usually you will use {@link #toString()} instead. ! * @param msb the most significant bytes ! * @param lsb the least significant bytes ! */ ! private static String toString(long msb, long lsb) ! { ! char[] uuidChars = new char[36]; ! ! digits(uuidChars, 0, 8, msb >> 32); ! uuidChars[8] = '-'; ! digits(uuidChars, 9, 4, msb >> 16); ! uuidChars[13] = '-'; ! digits(uuidChars, 14, 4, msb); ! uuidChars[18] = '-'; ! digits(uuidChars, 19, 4, lsb >> 48); ! uuidChars[23] = '-'; ! digits(uuidChars, 24, 12, lsb); ! ! return JAVA_LANG_ACCESS.createStringSharedChars(uuidChars); } ! private static void digits(char[] dest, int offset, int digits, long val) { ! long mask = 1L << (digits * 4); ! JAVA_LANG_ACCESS.formatUnsignedLong(mask | (val & (mask - 1)), 4, dest, offset, digits); } /** * Returns a hash code for this {@code UUID}. *