
com.moon.core.lang.LongUtil Maven / Gradle / Ivy
package com.moon.core.lang;
import com.moon.core.enums.Arrays2;
import com.moon.core.time.DateUtil;
import com.moon.core.util.TestUtil;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.Calendar;
import java.util.Date;
import static com.moon.core.lang.IntUtil.*;
import static com.moon.core.lang.ThrowUtil.noInstanceError;
import static java.lang.String.format;
/**
* @author moonsky
*/
public final class LongUtil {
private LongUtil() { noInstanceError(); }
public static long oneIfInvalid(CharSequence cs) { return defaultIfInvalid(cs, 1); }
public static long zeroIfInvalid(CharSequence cs) { return defaultIfInvalid(cs, 0); }
/**
* convert a CharSequence to int, if is an invalid CharSequence will return defaultVal
*
* @param cs
* @param defaultVal
*
* @return
*/
public static long defaultIfInvalid(CharSequence cs, long defaultVal) {
try {
if (cs == null) {
return defaultVal;
}
String value = cs.toString().trim().toLowerCase();
return value == null ? defaultVal : Long.parseLong(value);
} catch (Throwable t) {
return defaultVal;
}
}
public static boolean isLong(Object o) { return o != null && o.getClass() == Long.class; }
public static boolean matchLong(Object o) { return TestUtil.isIntegerValue(String.valueOf(o)); }
public static Long toLong(Boolean bool) { return bool == null ? null : (long) (bool ? 1 : 0); }
public static Long toLong(Character value) {
return value == null ? null : (TestUtil.isDigit(value.toString()) ? toLong(value.toString()) : Long.valueOf(
value));
}
public static Long toLong(Number value) { return value == null ? null : value.longValue(); }
public static Long toLong(CharSequence cs) {
if (cs == null) {
return null;
}
try {
return Long.parseLong(cs.toString().trim());
} catch (NumberFormatException e) {
try {
return DateUtil.toCalendar(cs).getTimeInMillis();
} catch (IllegalArgumentException ae) {
ae.initCause(e);
throw ae;
}
}
}
public static long toLongValue(Date date) { return date.getTime(); }
public static long toLongValue(Calendar calendar) { return calendar.getTimeInMillis(); }
public static long toLongValue(Boolean value) {
return value == null ? 0 : (value ? 1 : 0);
}
public static long toLongValue(CharSequence cs) {
return cs == null ? 0 : toLong(cs);
}
public static long toLongValue(Number value) { return value == null ? 0 : toLong(value); }
public static long toLongValueAtToday(LocalTime time) { return toLong(LocalDateTime.of(LocalDate.now(), time)); }
public static long toLongValue(LocalDate date) { return toLong(date.atStartOfDay()); }
public static long toLongValue(LocalDateTime date) {
return date.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli();
}
/**
* 目前基本数据 Util 内类似的方法均使用了极大的容忍度
* * 对于普通的转换均能得到预期结果;
* 对于复杂对象(数组或集合,但不包括自定义对象)的转换需要熟悉方法内部逻辑;
* * 如果对象 o 是一个集合或数组,当 o 只有一项时,返回这一项并且深度递归
* * 否则返回这个集合或数组的尺寸(size 或 length)
*
* Object value = null; // ================================ null
* boolean value = true; // =============================== 1
* boolean value = false; // ============================== 0
* char value = 'a'; // =================================== 97
* byte value = 1; // ===================================== 1
* int value = 1; // ====================================== 1
* short value = 1; // ==================================== 1
* long value = 1L; // ==================================== 1
* float value = 1F; // =================================== 1
* double value = 1F; // ================================== 1
* String value = "1"; // ================================= 1
* StringBuffer value = new StringBuffer("1"); // ========= 1
* StringBuilder value = new StringBuilder("1"); // ======= 1
* String value = " 1 "; // ============================ 1
* StringBuffer value = new StringBuffer(" 1 "); // ==== 1
* StringBuilder value = new StringBuilder(" 1 "); // == 1
* BigDecimal value = new BigDecimal("1"); // ============= 1
* BigInteger value = new BigInteger("1"); // ============= 1
* Collection value = new ArrayList(){{put(1)}}; // ======= 1(只有一项时)
* Collection value = new HashSet(){{put(1)}}; // ========= 1(只有一项时)
* Collection value = new TreeSet(){{put(1)}}; // ========= 1(只有一项时)
* Collection value = new LinkedList(){{put(1)}}; // ====== 1(只有一项时)
* Map value = new HashMap(){{put("key", 1)}}; // ========= 1(只有一项时)
*
* int[] value = {1, 2, 3, 4}; // ======================================== 4(大于一项时,返回 size)
* String[] value = {"1", "1", "1", "1"}; // ============================= 4(大于一项时,返回 size)
* Collection value = new ArrayList(){{put(1);put(1);put(1);}}; // ======= 3(大于一项时,返回 size)
* Map value = new HashMap(){{put("key", 1);put("name", 2);}}; // ======== 2(大于一项时,返回 size)
*
* Long result = LongUtil.toLong(value);
*
* @param object
*
* @return
*
* @see IntUtil#toIntValue(Object)
*/
public static Long toLong(Object object) {
if (object == null) {
return null;
}
if (object instanceof Long) {
return (Long) object;
}
if (object instanceof Number) {
return toLong((Number) object);
}
if (object instanceof CharSequence) {
return toLongValue(object.toString());
}
if (object instanceof Boolean) {
return toLong((Boolean) object);
}
if (object instanceof Date) {
return toLongValue((Date) object);
}
if (object instanceof Calendar) {
return toLongValue((Calendar) object);
}
try {
return toLong(ParseSupportUtil.unboxing(object));
} catch (Exception e) {
throw new IllegalArgumentException(format("Can not cast to int of: %s", object), e);
}
}
/**
* @param value
*
* @return
*
* @see IntUtil#toIntValue(Object)
* @see #toLongValue(Object)
*/
public static long toLongValue(Object value) {
Long result = toLong(value);
return result == null ? 0 : result;
}
public static long avg(long... values) {
long ret = 0;
int len = values.length;
for (int i = 0; i < len; ret += values[i++]) {
}
return ret / len;
}
public static long sum(long... values) {
long ret = 0;
int len = values.length;
for (int i = 0; i < len; i++) {
ret += values[i];
}
return ret;
}
public static long multiply(long... values) {
long ret = 1;
int le = values.length;
for (int i = 0; i < le; i++) {
ret *= values[i];
}
return ret;
}
public static long max(long... values) {
int len = values.length;
long ret = values[0];
for (int i = 1; i < len; i++) {
if (values[i] > ret) {
ret = values[i];
}
}
return ret;
}
public static Long min(long... values) {
int len = values.length;
long ret = values[0];
for (int i = 1; i < len; i++) {
if (values[i] < ret) {
ret = values[i];
}
}
return ret;
}
public static Long[] toObjectArr(long... values) {
return Arrays2.LONGS.toObjects(values);
}
public static long[] toPrimitiveArr(long defaultIfNull, Long... values) {
int length = values == null ? 0 : values.length;
if (length == 0) { return Arrays2.LONGS.empty(); }
long[] result = new long[length];
for (int i = 0; i < length; i++) {
result[i] = values[i] == null ? defaultIfNull : values[i];
}
return result;
}
/**
* 进制转换:支持十进制至 2 ~ 62 进制的转换
* (Copied from jdk 1.8: {@link Long#toString(long, int)})
*
* {@code Long}仅支持 36 进制转换,这里扩展到 62 进制
* 与{@link Long#parseLong(String)}、{@link Long#toString(long, int)}不兼容
*
* @param value 待转换的十进制长整型数
* @param radix 进制
*
* @return 转换后的字符串
*
* @see IntUtil#toString(int, int) 整形进制转换
*/
@SuppressWarnings("all")
public static String toString(long value, int radix) {
if (radix < Character.MIN_RADIX) {
radix = TEN;
}
if (radix > DIGITS.length) {
radix = DIGITS.length;
}
if (radix == TEN) {
return Long.toString(value);
}
int maxLen = radix < TEN ? 65 : 20;
char[] buf = new char[maxLen];
int charPos = maxLen - 1;
boolean negative = (value < 0);
if (!negative) {
value = -value;
}
while (value <= -radix) {
buf[charPos--] = DIGITS[(int) (-(value % radix))];
value = value / radix;
}
buf[charPos] = DIGITS[(int) (-value)];
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (maxLen - charPos));
}
/**
* 最大 62 进制字符串解析成十进制整数,和上面的{@link #toString(long, int)}相对应
* 与{@link Long#parseLong(String, int)}、{@link Long#toString(long, int)}不兼容
*
* @param s 待解析字符串
* @param radix 进制
*
* @return 解析后的整数
*
* @throws NumberFormatException 进制错误时抛出异常
*/
@SuppressWarnings("all")
public static long parseLong(String s, int radix) throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < 2) {
throw new NumberFormatException("radix " + radix + " less than 2");
}
if (radix > DIGITS.length) {
throw new NumberFormatException("radix " + radix + " greater than 62");
}
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 new NumberFormatException(s); }
if (len == 1) { // Cannot have lone "+" or "-"
throw new NumberFormatException(s);
}
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
// digit = Character.digit(s.charAt(i++), radix);
digit = CharUtil.toDigitMaxAs62(s.charAt(i++));
if (digit < 0) {
throw new NumberFormatException(s);
}
if (result < multmin) {
throw new NumberFormatException(s);
}
result *= radix;
if (result < limit + digit) {
throw new NumberFormatException(s);
}
result -= digit;
}
} else {
throw new NumberFormatException(s);
}
return negative ? result : -result;
}
/**
* 高压缩进制转换(最高支持 20902 进制, {@link IntUtil#MAX_CHINESE_CHAR}-{@link IntUtil#MIN_CHINESE_CHAR}+1)
*
* 这个区间是正则表达式汉字所在的区间,也是电脑能显示的一段较大的连续字符区间,返回字符串可满足计算机识别顺序;
*
* 还原原数字:{@link #parseCompressionString(String, int)}
*
* 兼容{@link #toString(long, int)} ;
* 兼容{@link #parseLong(String, int)};
* 不兼容{@link Long#toString(long, int)};
*
* @param value 值
* @param radix 进制
*
* @return 转换后的字符串
*/
@SuppressWarnings("all")
public static String toCompressionString(long value, int radix) {
if (radix < 63) {
return toString(value, radix);
}
final int min = MIN_CHINESE_CHAR, maxLen = 8;
radix = Math.min(MAX_RADIX, radix);
char[] buf = new char[maxLen];
boolean negative = (value < 0);
int charPos = maxLen - 1;
if (!negative) {
value = -value;
}
while (value <= -radix) {
buf[charPos--] = (char) (min - (value % radix));
value = value / radix;
}
buf[charPos] = (char) (min - value);
if (negative) {
buf[--charPos] = '-';
}
return new String(buf, charPos, (maxLen - charPos));
}
/**
* 高压缩进制解析(最高支持 20902 进制)
*
* 用于解析{@link #toCompressionString(long, int)}生成的字符串
*
* 兼容{@link #toString(long, int)};
* 不兼容{@link Long#toString(long, int)};
*
* @param s 字符串
* @param radix 进制
*
* @return 转换后的数字
*/
@SuppressWarnings("all")
public static long parseCompressionString(String s, int radix) {
if (radix < 63) {
return parseLong(s, radix);
}
if (s == null) {
throw new NumberFormatException("null");
}
if (radix > MAX_RADIX) {
throw new NumberFormatException("radix " + radix + " greater than " + 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 new NumberFormatException(s);
}
if (len == 1) {
// Cannot have lone "+" or "-"
throw new NumberFormatException(s);
}
i++;
}
multmin = limit / radix;
while (i < len) {
digit = s.charAt(i++) - MIN_CHINESE_CHAR;
if (digit < 0) {
throw new NumberFormatException(s);
}
if (result < multmin) {
throw new NumberFormatException(s);
}
result *= radix;
if (result < limit + digit) {
throw new NumberFormatException(s);
}
result -= digit;
}
} else {
throw new NumberFormatException(s);
}
return negative ? result : -result;
}
}