Long
缓存
private static class LongCache { private LongCache(){} static final Long cache[] = new Long[-(-128) + 127 + 1]; static { for(int i = 0; i < cache.length; i++) cache[i] = new Long(i - 128); } }
-
不同于Integer,缓存返回不可自由设置,固定-128 ~ 127
-
通过构造器创建的Long对象,不会从缓存中取值,==不适用
转化成不同进制下的字符串。
public static String toString(long i, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; if (radix == 10) return toString(i); char[] buf = new char[65]; int charPos = 64; boolean negative = (i < 0); if (!negative) { i = -i; } while (i <= -radix) { buf[charPos--] = Integer.digits[(int)(-(i % radix))]; i = i / radix; } buf[charPos] = Integer.digits[(int)(-i)]; if (negative) { buf[--charPos] = '-'; } return new String(buf, charPos, (65 - charPos)); }
同理Integer,不同在于位数不同。
public static String toUnsignedString(long i) { return toUnsignedString(i, 10); } public static String toUnsignedString(long i, int radix) { if (i >= 0) return toString(i, radix);// 正数直接使用toString转换 else { // 负数需要根据进制使用不同的转换方式 switch (radix) { case 2: return toBinaryString(i); case 4: return toUnsignedString0(i, 2); case 8: return toOctalString(i); case 10: long quot = (i >>> 1) / 5; long rem = i - quot * 10; return toString(quot) + rem; case 16: return toHexString(i); case 32: return toUnsignedString0(i, 5); default: return toUnsignedBigInteger(i).toString(radix); } } }
/** * 如果是正数,采用BigInteger.valueOf创建BigInteger对象 * 如果是负数,则拆分为高位和地位两个数,分别转换为无符号Long,再转为BigInteger,最后相加。 */ private static BigInteger toUnsignedBigInteger(long i) { if (i >= 0L) return BigInteger.valueOf(i); else { int upper = (int) (i >>> 32); int lower = (int) i; // return (upper << 32) + lower return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); } }
public static String toHexString(long i) { return toUnsignedString0(i, 4); } public static String toOctalString(long i) { return toUnsignedString0(i, 3); } public static String toBinaryString(long i) { return toUnsignedString0(i, 1); } static String toUnsignedString0(long val, int shift) { // 确定val的位数 int mag = Long.SIZE - Long.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); char[] buf = new char[chars]; formatUnsignedLong(val, shift, buf, 0, chars); return new String(buf, true); } /** * 求一个数二进制表示,前面为0的个数。负数符号位为1,前面0个数为0 * 这里和Integer的类似,只不过,多以一步操作, i>>>32, 将一个数变小了。 */ public static int numberOfLeadingZeros(long i) { // HD, Figure 5-6 if (i == 0) return 64; int n = 1; int x = (int)(i >>> 32); if (x == 0) { n += 32; x = (int)i; } if (x >>> 16 == 0) { n += 16; x <<= 16; } if (x >>> 24 == 0) { n += 8; x <<= 8; } if (x >>> 28 == 0) { n += 4; x <<= 4; } if (x >>> 30 == 0) { n += 2; x <<= 2; } n -= x >>> 31; return n; } static int formatUnsignedLong(long val, int shift, char[] buf, int offset, int len) { int charPos = len; int radix = 1 << shift; int mask = radix - 1; do { buf[offset + --charPos] = Integer.digits[((int) val) & mask]; val >>>= shift; } while (val != 0 && charPos > 0); return charPos; }
public static String toString(long i) { if (i == Long.MIN_VALUE) return "-9223372036854775808"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(buf, true); } // 每次乘以10,比较大小,直到x小于定义p数,此时乘的次数就是x的位数。 static int stringSize(long x) { long p = 10; for (int i=1; i<19; i++) { if (x < p) return i; p = 10*p; } return 19; } static void getChars(long i, int index, char[] buf) { long q; int r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } while (i > Integer.MAX_VALUE) { q = i / 100; // really: r = i - (q * 100); r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); i = q; buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = Integer.DigitTens[r]; } int q2; int i2 = (int)i; while (i2 >= 65536) { q2 = i2 / 100; // really: r = i2 - (q * 100); r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); i2 = q2; buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = Integer.DigitTens[r]; } for (;;) { q2 = (i2 * 52429) >>> (16+3); r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ... buf[--charPos] = Integer.digits[r]; i2 = q2; if (i2 == 0) break; } if (sign != 0) { buf[--charPos] = sign; } }
这里对比Integer,可发现,多了一步,就是while (i > Integer.MAX_VALUE),原理是一样的,就是把数的大小缩小到Integer的范围,再采用Integer的对应方法。
字符串转long
public static long parseLong(String s) throws NumberFormatException { return parseLong(s, 10); } public static long parseLong(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } long result = 0; boolean negative = false; int i = 0, len = s.length(); long limit = -Long.MAX_VALUE; long multmin; int digit; if (len > 0) { char firstChar = s.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Long.MIN_VALUE; } else if (firstChar != '+') throw NumberFormatException.forInputString(s); if (len == 1) // Cannot have lone "+" or "-" throw NumberFormatException.forInputString(s); i++; } multmin = limit / radix; while (i < len) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw NumberFormatException.forInputString(s); } if (result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { throw NumberFormatException.forInputString(s); } result -= digit; } } else { throw NumberFormatException.forInputString(s); } return negative ? result : -result; }
public static long parseUnsignedLong(String s) throws NumberFormatException { return parseUnsignedLong(s, 10); } public static long parseUnsignedLong(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } int len = s.length(); if (len > 0) { char firstChar = s.charAt(0); if (firstChar == '-') { throw new NumberFormatException(String.format("Illegal leading minus sign " + "on unsigned string %s.", s)); } else { if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits return parseLong(s, radix); } // No need for range checks on len due to testing above. long first = parseLong(s.substring(0, len - 1), radix); int second = Character.digit(s.charAt(len - 1), radix); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + s); } long result = first * radix + second; if (compareUnsigned(result, first) < 0) { /* * The maximum unsigned value, (2^64)-1, takes at * most one more digit to represent than the * maximum signed value, (2^63)-1. Therefore, * parsing (len - 1) digits will be appropriately * in-range of the signed parsing. In other * words, if parsing (len -1) digits overflows * signed parsing, parsing len digits will * certainly overflow unsigned parsing. * * The compareUnsigned check above catches * situations where an unsigned overflow occurs * incorporating the contribution of the final * digit. */ throw new NumberFormatException(String.format("String value %s exceeds " + "range of unsigned long.", s)); } return result; } } else { throw NumberFormatException.forInputString(s); } }
valueOf创建Long对象
public static Long valueOf(String s, int radix) throws NumberFormatException { return Long.valueOf(parseLong(s, radix)); }
public static Long valueOf(String s) throws NumberFormatException { return Long.valueOf(parseLong(s, 10)); }
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
decode方法
public static Long decode(String nm) throws NumberFormatException {
int radix = 10;
int index = 0;
boolean negative = false;
Long result;
if (nm.length() == 0)
throw new NumberFormatException("Zero length string");
char firstChar = nm.charAt(0);
// Handle sign, if present
if (firstChar == '-') {
negative = true;
index++;
} else if (firstChar == '+')
index++;
// Handle radix specifier, if present
if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
index += 2;
radix = 16;
}
else if (nm.startsWith("#", index)) {
index ++;
radix = 16;
}
else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
index ++;
radix = 8;
}
if (nm.startsWith("-", index) || nm.startsWith("+", index))
throw new NumberFormatException("Sign character in wrong position");
try {
result = Long.valueOf(nm.substring(index), radix);
result = negative ? Long.valueOf(-result.longValue()) : result;
} catch (NumberFormatException e) {
// If number is Long.MIN_VALUE, we'll end up here. The next line
// handles this case, and causes any genuine format error to be
// rethrown.
String constant = negative ? ("-" + nm.substring(index))
: nm.substring(index);
result = Long.valueOf(constant, radix);
}
return result;
}
构造器创建Long对象
private final long value; public Long(long value) { this.value = value; } public Long(String s) throws NumberFormatException { this.value = parseLong(s, 10); }
继承Number类,数值转换
public byte byteValue() { return (byte)value; } public short shortValue() { return (short)value; } public int intValue() { return (int)value; } public long longValue() { return value; } public float floatValue() { return (float)value; } public double doubleValue() { return (double)value; }
hashCode以及equals方法
@Override public int hashCode() { return Long.hashCode(value); } public static int hashCode(long value) { return (int)(value ^ (value >>> 32)); } public boolean equals(Object obj) { if (obj instanceof Long) { return value == ((Long)obj).longValue(); } return false; }
getLong
获取系统某个字符串属性代表的long值
public static Long getLong(String nm) { return getLong(nm, null); } public static Long getLong(String nm, long val) { Long result = Long.getLong(nm, null); return (result == null) ? Long.valueOf(val) : result; } public static Long getLong(String nm, Long val) { String v = null; try { v = System.getProperty(nm); } catch (IllegalArgumentException | NullPointerException e) { } if (v != null) { try { return Long.decode(v); } catch (NumberFormatException e) { } } return val; }
比较
public int compareTo(Long anotherLong) { return compare(this.value, anotherLong.value); } public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); } public static int compareUnsigned(long x, long y) { return compare(x + MIN_VALUE, y + MIN_VALUE); }
运算 1.8 新增
public static long divideUnsigned(long dividend, long divisor) { // 有符号比较 if (divisor < 0L) { // 根据被除数和除数的相对大小,答案必须是0或1。 return (compareUnsigned(dividend, divisor)) < 0 ? 0L :1L; } // 两个输入均为非负 if (dividend > 0) return dividend/divisor; else { /* * 对于简单代码,请使用BigInteger。直接以long操作的形式编写更长更快的代码是可能的;有关除法和余数算法,请参阅“Hacker's Delight” */ return toUnsignedBigInteger(dividend). divide(toUnsignedBigInteger(divisor)).longValue(); } }
public static long remainderUnsigned(long dividend, long divisor) { if (dividend > 0 && divisor > 0) { // signed comparisons return dividend % divisor; } else { if (compareUnsigned(dividend, divisor) < 0) // Avoid explicit check for 0 divisor return dividend; else return toUnsignedBigInteger(dividend). remainder(toUnsignedBigInteger(divisor)).longValue(); } }
public static long sum(long a, long b) { return a + b; } public static long max(long a, long b) { return Math.max(a, b); } public static long min(long a, long b) { return Math.min(a, b); }
其他方法
// 取 i 这个数的二进制形式最左边的最高一位且高位后面全部补零,最后返回int型的结果。 // 给它传入一个数字,它将返回小于等于这个数字的一个2的幂次方数。 // https://www.cnblogs.com/nicerblog/p/11431181.html public static long highestOneBit(long i) { // HD, Figure 3-1 i |= (i >> 1); i |= (i >> 2); i |= (i >> 4); i |= (i >> 8); i |= (i >> 16); i |= (i >> 32); return i - (i >>> 1); }
public static long lowestOneBit(long i) { // HD, Section 2-1 return i & -i; }
public static int numberOfLeadingZeros(long i) { // HD, Figure 5-6 if (i == 0) return 64; int n = 1; int x = (int)(i >>> 32); if (x == 0) { n += 32; x = (int)i; } if (x >>> 16 == 0) { n += 16; x <<= 16; } if (x >>> 24 == 0) { n += 8; x <<= 8; } if (x >>> 28 == 0) { n += 4; x <<= 4; } if (x >>> 30 == 0) { n += 2; x <<= 2; } n -= x >>> 31; return n; }
public static int numberOfTrailingZeros(long i) { // HD, Figure 5-14 int x, y; if (i == 0) return 64; int n = 63; y = (int)i; if (y != 0) { n = n -32; x = y; } else x = (int)(i>>>32); y = x <<16; if (y != 0) { n = n -16; x = y; } y = x << 8; if (y != 0) { n = n - 8; x = y; } y = x << 4; if (y != 0) { n = n - 4; x = y; } y = x << 2; if (y != 0) { n = n - 2; x = y; } return n - ((x << 1) >>> 31); }
public static int bitCount(long i) { // HD, Figure 5-14 i = i - ((i >>> 1) & 0x5555555555555555L); i = (i & 0x3333333333333333L) + ((i >>> 2) & 0x3333333333333333L); i = (i + (i >>> 4)) & 0x0f0f0f0f0f0f0f0fL; i = i + (i >>> 8); i = i + (i >>> 16); i = i + (i >>> 32); return (int)i & 0x7f; }
public static long rotateRight(long i, int distance) { return (i >>> distance) | (i << -distance); }
public static long reverse(long i) { // HD, Figure 7-1 i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L; i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L; i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL; i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; i = (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48); return i; }
public static long reverse(long i) { // HD, Figure 7-1 i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L; i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L; i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL; i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; i = (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48); return i; }
public static long reverseBytes(long i) { i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; return (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48); }
public static long reverseBytes(long i) { i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL; return (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48); }