All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moon.core.lang.IntUtil Maven / Gradle / Ivy

package com.moon.core.lang;

import com.moon.core.util.CollectUtil;
import com.moon.core.util.function.BiIntFunction;
import com.moon.core.util.function.TableIntFunction;

import java.util.Collection;
import java.util.Iterator;
import java.util.function.ToIntFunction;

import static com.moon.core.enums.Strings.*;
import static com.moon.core.lang.ThrowUtil.noInstanceError;
import static com.moon.core.util.TestUtil.isIntegerValue;
import static java.lang.String.format;

/**
 * @author moonsky
 */
public final class IntUtil {

    private IntUtil() { noInstanceError(); }


    public static boolean isInt(Object o) { return o instanceof Integer; }

    public static boolean matchInt(CharSequence o) { return isIntegerValue(String.valueOf(o)); }

    /*
     * -------------------------------------------------------------------------------------------
     * converter
     * -------------------------------------------------------------------------------------------
     */

    public static int toIntValue(Boolean bool) { return toIntValue(bool != null && bool); }

    public static int toIntValue(long value) { return (int) value; }

    public static int toIntValue(float value) { return (int) value; }

    public static int toIntValue(double value) { return (int) value; }

    public static int toIntValue(boolean value) { return value ? 1 : 0; }

    public static int toIntValue(CharSequence cs) {
        if (cs == null) {
            return 0;
        } else {
            String str = cs.toString().trim();
            return str.length() > 0 ? Integer.parseInt(str) : 0;
        }
    }

    /*
     * -------------------------------------------------------------------------------------------
     * defaulter
     * -------------------------------------------------------------------------------------------
     */

    /**
     * convert a CharSequence to int, if is an invalid CharSequence will return defaultVal
     *
     * @param cs         数字字符串
     * @param defaultVal 默认值
     *
     * @return 数值
     */
    public static int defaultIfInvalid(CharSequence cs, int defaultVal) {
        try {
            if (cs == null) {
                return defaultVal;
            }
            String value = cs.toString().trim().toLowerCase();
            return StringUtil.isEmpty(value) ? defaultVal : Integer.parseInt(value);
        } catch (Exception e) {
            return defaultVal;
        }
    }

    /**
     * convert a CharSequence to int, if is an invalid CharSequence will return 0
     *
     * @param cs 数字字符串
     *
     * @return 数字
     */
    public static int zeroIfInvalid(CharSequence cs) {
        return defaultIfInvalid(cs, 0);
    }

    /**
     * convert a CharSequence to int, if is an invalid CharSequence will return 1
     *
     * @param cs 数字字符串
     *
     * @return 数字
     */
    public static int oneIfInvalid(CharSequence cs) {
        return defaultIfInvalid(cs, 1);
    }

    /*
     * -------------------------------------------------------------------------------------------
     * calculator
     * -------------------------------------------------------------------------------------------
     */

    public static int[] toInts(int... values) { return values; }

    public static int[] toInts(String... values) {
        return toInts(Integer::parseInt, values);
    }

    @SafeVarargs
    public static  int[] toInts(ToIntFunction transformer, T... values) {
        if (values == null) {
            return null;
        }
        final int length = values.length;
        int[] ints = new int[length];
        for (int i = 0; i < length; i++) {
            ints[i] = transformer.applyAsInt(values[i]);
        }
        return ints;
    }

    public static  int[] toInts(Collection collect, ToIntFunction transformer) {
        if (collect == null) {
            return null;
        }
        int index = 0;
        int[] ints = new int[collect.size()];
        for (T item : collect) {
            ints[index++] = transformer.applyAsInt(item);
        }
        return ints;
    }

    public static int max(int... values) {
        int len = values.length;
        int ret = values[0];
        for (int i = 1; i < len; i++) {
            if (values[i] > ret) {
                ret = values[i];
            }
        }
        return ret;
    }

    public static int min(int... values) {
        int len = values.length;
        int ret = values[0];
        for (int i = 1; i < len; i++) {
            if (values[i] < ret) {
                ret = values[i];
            }
        }
        return ret;
    }

    public static int avg(int... values) {
        int ret = 0;
        int len = values.length;
        for (int i = 0; i < len; ret += values[i++]) {
        }
        return ret / len;
    }

    public static int sum(int... values) {
        int ret = 0;
        int len = values.length;
        for (int i = 0; i < len; i++) {
            ret += values[i];
        }
        return ret;
    }

    public static int multiply(int... values) {
        int ret = 1;
        int le = values.length;
        for (int i = 0; i < le; i++) {
            ret *= values[i];
        }
        return ret;
    }

    /**
     * 目前基本数据 Util 内类似的方法均使用了极大的容忍度
     * * 对于普通的转换均能得到预期结果;
     * 对于复杂对象(数组或集合,但不包括自定义对象)的转换需要熟悉方法内部逻辑;
     * * 如果对象 o 是一个集合或数组,当 o 只有一项时,返回这一项并且深度递归
     * * 否则返回这个集合或数组的尺寸(size 或 length)
     * 

* 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) *

* int result = IntUtil.toIntValue(value); * * @param o 待转换值 * * @return 转换后的值 * * @see BooleanUtil#toBoolean(Object) * @see BooleanUtil#toBooleanValue(Object) * @see CharUtil#toCharValue(Object) * @see CharacterUtil#toCharacter(Object) * @see ByteUtil#toByteValue(Object) * @see ByteUtil#toByte(Object) * @see ShortUtil#toShort(Object) * @see ShortUtil#toShortValue(Object) * @see IntegerUtil#toInteger(Object) * @see LongUtil#toLongValue(Object) * @see LongUtil#toLong(Object) * @see FloatUtil#toFloat(Object) * @see FloatUtil#toFloatValue(Object) * @see DoubleUtil#toDoubleValue(Object) * @see DoubleUtil#toDouble(Object) */ public static int toIntValue(Object o) { if (o == null) { return 0; } if (o instanceof Integer) { return (Integer) o; } if (o instanceof Number) { return ((Number) o).intValue(); } if (o instanceof CharSequence) { return toIntValue((CharSequence) o); } if (o instanceof Character) { return (Character) o; } if (o instanceof Boolean) { return (boolean) o ? 1 : 0; } try { return toIntValue(ParseSupportUtil.unboxing(o)); } catch (Exception e) { throw new IllegalArgumentException(format("Can not cast to int of: %s", o), e); } } /** * 聚合函数,参照 JavaScript 中 Array.reduce(..) 实现 *

     * 1. 接受一个数组作为源数据;
     * 2. 一个处理器,处理器接收两个参数(总值, 当前项),然后返回总值,下一次迭代接受到的总值是上一次的返回结果;
     *       其中当前项也是索引,索引相对{@link #reduce(int, BiIntFunction, Object)}少一个参数
     * 3. 初始值,作为第一次传入处理器的参数
     * 
* * @param count 迭代次数 * @param reducer 聚合函数 * @param totalValue 返回结果 * @param 返回值类型 * * @return 返回最后一项处理完后的结果 * * @see ArrayUtil#reduce(Object[], TableIntFunction, Object) * @see CollectUtil#reduce(Iterable, TableIntFunction, Object) * @see CollectUtil#reduce(Iterator, TableIntFunction, Object) */ public static T reduce(int count, BiIntFunction reducer, T totalValue) { for (int i = 0; i < count; i++) { totalValue = reducer.apply(totalValue, i); } return totalValue; } final static char[] DIGITS = toCharArray(NUMBERS, UPPERS, LOWERS); final static int TEN = 10; /** * 进制转换:支持十进制至 2 ~ 62 进制的转换 * (Copied from jdk 1.8: {@link Integer#toString(int, int)}) *

* {@code Integer}仅支持 36 进制转换,这里扩展到 62 进制 * 与{@link Integer#parseInt(String)}、{@link Integer#toString(int, int)}不兼容 * * @param value 待转换的十进制整型数 * @param radix 进制 * * @return 转换后的字符串 * * @see LongUtil#toString(long, int) 长整形进制转换 */ public static String toString(int value, int radix) { if (radix < Character.MIN_RADIX) { radix = TEN; } if (radix > DIGITS.length) { radix = DIGITS.length; } if (radix == TEN) { return Integer.toString(value); } int maxLen = radix < TEN ? 33 : 11; char[] buf = new char[maxLen]; boolean negative = (value < 0); int charPos = maxLen - 1; if (!negative) { value = -value; } while (value <= -radix) { buf[charPos--] = DIGITS[-(value % radix)]; value = value / radix; } buf[charPos] = DIGITS[-value]; if (negative) { buf[--charPos] = '-'; } return new String(buf, charPos, (maxLen - charPos)); } /** * 最大 62 进制字符串解析成十进制整数,和上面的{@link #toString(int, int)}相对应 * 与{@link Integer#parseInt(String, int)}、{@link Integer#toString(int, int)}不兼容 * * @param s 待解析字符串 * @param radix 进制 * * @return 解析后的整数 * * @throws NumberFormatException 进制错误时抛出异常 */ @SuppressWarnings("all") public static int parseInt(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"); } int result = 0; boolean negative = false; int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit; if (len > 0) { char firstChar = s.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Integer.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 = 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; } final static char MIN_CHINESE_CHAR = '\u4e00'; final static char MAX_CHINESE_CHAR = '\u9fa5'; public final static int MAX_RADIX = MAX_CHINESE_CHAR - MIN_CHINESE_CHAR + 1; /** * 高压缩进制转换(最高支持 20902 进制, {@link #MAX_CHINESE_CHAR}-{@link #MIN_CHINESE_CHAR}+1) *

* 这个区间是正则表达式汉字所在的区间,也是电脑能显示的一段较大的连续字符区间; *

* 还原原数字:{@link #parseCompressionString(String, int)} *

* 兼容{@link #toString(int, int)}; * 兼容{@link #parseInt(String, int)}; * 不兼容{@link Integer#toString(int, int)}; * * @param value 值 * @param radix 进制 * * @return 转换后的字符串 */ public static String toCompressionString(int value, int radix) { if (radix < 63) { return toString(value, radix); } final int min = MIN_CHINESE_CHAR, maxLen = 5; 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(int, int)}生成的字符串 *

* 兼容{@link #toString(int, int)}; * 不兼容{@link Integer#toString(int, int)}; * * @param s 字符串 * @param radix 进制 * * @return 转换后的数字 */ @SuppressWarnings("all") public static int parseCompressionString(String s, int radix) { if (radix < 63) { return parseInt(s, radix); } if (s == null) { throw new NumberFormatException("null"); } if (radix > MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than " + MAX_RADIX); } int result = 0; boolean negative = false; int i = 0, len = s.length(); int limit = -Integer.MAX_VALUE; int multmin; int digit; if (len > 0) { char firstChar = s.charAt(0); if (firstChar < '0') { // Possible leading "+" or "-" if (firstChar == '-') { negative = true; limit = Integer.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; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy