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

com.iofairy.top.O Maven / Gradle / Ivy

Go to download

Functional Programming for Java 8+ and compatible with the modular system of Java 9+.

There is a newer version: 0.5.10
Show newest version
/*
 * Copyright (C) 2021 iofairy, 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.iofairy.top;

import com.iofairy.except.UnexpectedTypeException;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.*;

/**
 * Global Variables And Methods for {@link Object} Operations. 
* {@link Object} 相关操作的常用变量与函数。
* >>>>>>
* 采用简单类名 O (Object / Other) 模拟类似 Kotlin 的 Top-level function(顶级函数、全局函数) * * @since 0.3.0 */ public final class O { /** * Creates a new empty array with the specified array class type.
* 根据传入的数组类型,创建一个该类型的空数组。 * * @param tsClass array type * @param array type * @return empty array * @since 0.2.2 */ public static T[] array0(Class tsClass) { return arrayM(tsClass, 0); } /** * Creates a new empty array with the specified class type.
* 根据传入的类型,创建一个该类型的空数组。 * * @param tClass array type * @param array type * @return empty array * @since 0.2.2 */ public static T[] arrayO(Class tClass) { return arrayN(tClass, 0); } /** * Creates a new array with the specified array class type and length.
* * @param tsClass array type * @param length array length * @param array type * @return new array with length * @since 0.3.1 */ public static T[] arrayM(Class tsClass, int length) { @SuppressWarnings("unchecked") T[] ts = (T[]) Array.newInstance(tsClass.getComponentType(), length); return ts; } /** * Creates a new array with the specified class type and length.
* * @param tClass array type * @param length array length * @param array type * @return new array with length * @since 0.3.1 */ public static T[] arrayN(Class tClass, int length) { @SuppressWarnings("unchecked") T[] ts = (T[]) Array.newInstance(tClass, length); return ts; } /** * Creates a new array with the specified array class type and length, * and assigns the t object reference to each element of array.
* * @param tsClass array type * @param length array length * @param t t object * @param array type * @return new array with length and fill t elements * @since 0.3.1 */ public static T[] arrayFillM(Class tsClass, int length, T t) { T[] ts = arrayM(tsClass, length); Arrays.fill(ts, t); return ts; } /** * Creates a new array with the specified class type and length, * and assigns the t object reference to each element of array.
* * @param tClass array type * @param length array length * @param t t object * @param array type * @return new array with length and fill t elements * @since 0.3.1 */ public static T[] arrayFillN(Class tClass, int length, T t) { T[] ts = arrayN(tClass, length); Arrays.fill(ts, t); return ts; } /** * Get {@link Throwable}'s all causes order by the shallow and deep
* 获取所有 {@link Throwable} 的 causes,由浅至深排序 * * @param throwable Throwable * @return current {@code throwable} and throwable's all causes * @since 0.3.4 */ public static List causeTrace(Throwable throwable) { if (throwable == null) return null; List causes = new ArrayList<>(); causes.add(throwable); Throwable cause = throwable; while ((cause = cause.getCause()) != null) { causes.add(cause); } return causes; } /** * Gets the first object that is not {@code null}.
* 获取第一个不为 {@code null} 的值 * * @param rs object array * @param return type * @return first non {@code null} object * @since 0.0.7 */ @SafeVarargs public static R firstNonNull(R... rs) { if (G.isEmpty(rs)) return null; for (R r : rs) { if (r != null) return r; } return null; } /** * Validate the key-value pair array when creating a map * * @param allowKeyIsNull Whether null keys are allowed * @param whetherKeyIsString Whether keys are of string type * @param whetherValueIsString Whether values are of string type * @param kvs Array of key-value pairs, in the form of {@code key1, value1, key2, value2, ...} * @since 0.4.19 */ public static void verifyMapKV(boolean allowKeyIsNull, boolean whetherKeyIsString, boolean whetherValueIsString, Object... kvs) { if (kvs != null) { if (kvs.length % 2 != 0) throw new RuntimeException("The parameters length must be even. "); for (int i = 0; i < kvs.length; i++) { Object o = kvs[i]; if (i % 2 == 0) { // Validate elements at even indexes (keys) if (o == null && !allowKeyIsNull) { throw new NullPointerException("Index: " + i + ". This parameter is a key, the key must be not null. "); } if (whetherKeyIsString && o != null && !(o instanceof String)) { throw new UnexpectedTypeException("Index: " + i + ". This parameter is a key, the key must be `java.lang.String` type. "); } } else { // Validate elements at odd indexes (values) if (whetherValueIsString && o != null && !(o instanceof String)) { throw new UnexpectedTypeException("Index: " + i + ". This parameter is a value, the value must be `java.lang.String` type. "); } } } } } /** * Convert dynamic arguments of type {@link Object} to an array of Objects.
* * @param objs Variable arguments of type {@link Object} * @return An {@link Object} array * @since 0.5.0 */ public static Object[] args(Object... objs) { return objs; } /** * Convert dynamic arguments of type {@link CharSequence} to an array of CharSequences.
* * @param cs Variable arguments of type {@link CharSequence} * @return An {@link CharSequence} array * @since 0.5.1 */ public static CharSequence[] args(CharSequence... cs) { return cs; } /** * Convert dynamic arguments of type {@link String} to an array of Strings.
* * @param ss Variable arguments of type {@link String} * @return An {@link String} array * @since 0.5.1 */ public static String[] args(String... ss) { return ss; } /** * Returns the provided default value if the specified value is null; otherwise, returns the original value. * * @param value The original value * @param defaultValue The value to return if the original value is null * @param The generic type * @return The default value if it's null, otherwise, returns the original value. * @since 0.5.2 */ public static T valueIfNull(T value, T defaultValue) { return value == null ? defaultValue : value; } /** * Returns the provided default value if the specified value is empty; otherwise, returns the original value. * * @param value The original value * @param defaultValue The value to return if the original value is empty * @param The generic type * @return The default value if it's empty, otherwise, returns the original value. * @since 0.5.2 */ public static T valueIfEmpty(T value, T defaultValue) { return G.isEmpty(value) ? defaultValue : value; } /** * Returns the provided default value if the specified value is blank; otherwise, returns the original value. * * @param value The original value * @param defaultValue The value to return if the original value is blank * @param The generic type * @return The default value if it's blank, otherwise, returns the original value. * @since 0.5.2 */ public static T valueIfBlank(T value, T defaultValue) { return S.isBlank(value) ? defaultValue : value; } /** * Returns the default value if the condition is {@code true}; otherwise, returns the original value. Equivalent to Ternary Operator. * * @param condition The boolean condition to check. If true, the default value will be returned. * @param value The original value * @param defaultValue The value to return when the condition is {@code true} * @param The generic type * @return The default value if the condition is {@code true}, otherwise, returns the original value. * @since 0.5.2 */ public static T valueIfElse(boolean condition, T value, T defaultValue) { return condition ? defaultValue : value; } /*################################################################################### ************************************************************************************ ------------------------------------------------------------------------------------ *********************** index of maximum value in arrays *********************** ------------------------------------------------------------------------------------ ************************************************************************************ ###################################################################################*/ /** * Getting index of maximum value in {@code byte[]} * * @param bs {@code byte[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(byte[] bs) { if (G.isEmpty(bs)) return -1; int index = 0; byte max = bs[0]; for (int i = 1; i < bs.length; i++) { byte iByte = bs[i]; if (iByte > max) { max = iByte; index = i; } } return index; } /** * Getting index of maximum value in {@code short[]} * * @param ss {@code short[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(short[] ss) { if (G.isEmpty(ss)) return -1; int index = 0; short max = ss[0]; for (int i = 1; i < ss.length; i++) { short iShort = ss[i]; if (iShort > max) { max = iShort; index = i; } } return index; } /** * Getting index of maximum value in {@code char[]} * * @param cs {@code char[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(char[] cs) { if (G.isEmpty(cs)) return -1; int index = 0; char max = cs[0]; for (int i = 1; i < cs.length; i++) { char iChar = cs[i]; if (iChar > max) { max = iChar; index = i; } } return index; } /** * Getting index of maximum value in {@code int[]} * * @param is {@code int[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(int[] is) { if (G.isEmpty(is)) return -1; int index = 0; int max = is[0]; for (int i = 1; i < is.length; i++) { int iInt = is[i]; if (iInt > max) { max = iInt; index = i; } } return index; } /** * Getting index of maximum value in {@code long[]} * * @param ls {@code long[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(long[] ls) { if (G.isEmpty(ls)) return -1; int index = 0; long max = ls[0]; for (int i = 1; i < ls.length; i++) { long iLong = ls[i]; if (iLong > max) { max = iLong; index = i; } } return index; } /** * Getting index of maximum value in {@code float[]} ({@link Float#NaN} will be ignored) * * @param fs {@code float[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(float[] fs) { if (G.isEmpty(fs)) return -1; int index = -1; float max = Float.NaN; for (int i = 0; i < fs.length; i++) { float iFloat = fs[i]; if (!Float.isNaN(iFloat)) { if (Float.isNaN(max)) { max = iFloat; index = i; } else { if (iFloat > max) { max = iFloat; index = i; } } } } return index; } /** * Getting index of maximum value in {@code double[]} ({@link Double#NaN} will be ignored) * * @param ds {@code double[]} * @return index of maximum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMax(double[] ds) { if (G.isEmpty(ds)) return -1; int index = -1; double max = Double.NaN; for (int i = 0; i < ds.length; i++) { double iDouble = ds[i]; if (!Double.isNaN(iDouble)) { if (Double.isNaN(max)) { max = iDouble; index = i; } else { if (iDouble > max) { max = iDouble; index = i; } } } } return index; } /*################################################################################### ************************************************************************************ ------------------------------------------------------------------------------------ *********************** index of minimum value in arrays *********************** ------------------------------------------------------------------------------------ ************************************************************************************ ###################################################################################*/ /** * Getting index of minimum value in {@code byte[]} * * @param bs {@code byte[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(byte[] bs) { if (G.isEmpty(bs)) return -1; int index = 0; byte min = bs[0]; for (int i = 1; i < bs.length; i++) { byte iByte = bs[i]; if (iByte < min) { min = iByte; index = i; } } return index; } /** * Getting index of minimum value in {@code short[]} * * @param ss {@code short[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(short[] ss) { if (G.isEmpty(ss)) return -1; int index = 0; short min = ss[0]; for (int i = 1; i < ss.length; i++) { short iShort = ss[i]; if (iShort < min) { min = iShort; index = i; } } return index; } /** * Getting index of minimum value in {@code char[]} * * @param cs {@code char[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(char[] cs) { if (G.isEmpty(cs)) return -1; int index = 0; char min = cs[0]; for (int i = 1; i < cs.length; i++) { char iChar = cs[i]; if (iChar < min) { min = iChar; index = i; } } return index; } /** * Getting index of minimum value in {@code int[]} * * @param is {@code int[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(int[] is) { if (G.isEmpty(is)) return -1; int index = 0; int min = is[0]; for (int i = 1; i < is.length; i++) { int iInt = is[i]; if (iInt < min) { min = iInt; index = i; } } return index; } /** * Getting index of minimum value in {@code long[]} * * @param ls {@code long[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(long[] ls) { if (G.isEmpty(ls)) return -1; int index = 0; long min = ls[0]; for (int i = 1; i < ls.length; i++) { long iLong = ls[i]; if (iLong < min) { min = iLong; index = i; } } return index; } /** * Getting index of minimum value in {@code float[]} ({@link Float#NaN} will be ignored) * * @param fs {@code float[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(float[] fs) { if (G.isEmpty(fs)) return -1; int index = -1; float min = Float.NaN; for (int i = 0; i < fs.length; i++) { float iFloat = fs[i]; if (!Float.isNaN(iFloat)) { if (Float.isNaN(min)) { min = iFloat; index = i; } else { if (iFloat < min) { min = iFloat; index = i; } } } } return index; } /** * Getting index of minimum value in {@code double[]} ({@link Double#NaN} will be ignored) * * @param ds {@code double[]} * @return index of minimum value, {@code -1} if not found. * @since 0.3.4 */ public static int indexOfMin(double[] ds) { if (G.isEmpty(ds)) return -1; int index = -1; double min = Double.NaN; for (int i = 0; i < ds.length; i++) { double iDouble = ds[i]; if (!Double.isNaN(iDouble)) { if (Double.isNaN(min)) { min = iDouble; index = i; } else { if (iDouble < min) { min = iDouble; index = i; } } } } return index; } /** * Returns {@code true} if this {@code Number} value is {@link Double} or {@link DoubleAdder} or {@link DoubleAccumulator}, {@code false} otherwise. * * @param number number * @return Returns {@code true} if this {@code Number} value is {@link Double} or {@link DoubleAdder} or {@link DoubleAccumulator}, {@code false} otherwise. * @since 0.3.4 */ public static boolean isDouble(Number number) { return number instanceof Double || number instanceof DoubleAdder || number instanceof DoubleAccumulator; } /** * Returns {@code true} if this {@code Number} value is {@link Float} or {@link #isDouble(Number)}, {@code false} otherwise. * * @param number number * @return Returns {@code true} if this {@code Number} value is {@link Float} or {@link #isDouble(Number)}, {@code false} otherwise. * @since 0.3.6 */ public static boolean isFloat(Number number) { return number instanceof Float || isDouble(number); } /** * Returns {@code true} if this {@code Number} value is {@link Long} or {@link AtomicLong} or {@link LongAdder} * or {@link LongAccumulator}, {@code false} otherwise. * * @param number number * @return Returns {@code true} if this {@code Number} value is {@link Long} or {@link AtomicLong} or {@link LongAdder} * or {@link LongAccumulator}, {@code false} otherwise. * @since 0.3.6 */ public static boolean isLong(Number number) { return number instanceof Long || number instanceof AtomicLong || number instanceof LongAdder || number instanceof LongAccumulator; } /** * Returns {@code true} if this {@code Number} value is {@link Byte} or {@link Short} or {@link Integer} * or {@link AtomicInteger} or {@link #isLong(Number)}, {@code false} otherwise. * * @param number number * @return Returns {@code true} if this {@code Number} value is {@link Byte} or {@link Short} or {@link Integer} * or {@link AtomicInteger} or {@link #isLong(Number)}, {@code false} otherwise. * @since 0.3.6 */ public static boolean isInteger(Number number) { return number instanceof Byte || number instanceof Short || number instanceof Integer || number instanceof AtomicInteger || isLong(number); } /** * Returns {@code true} if this {@code Number} value is * a {@code Not-a-Number (NaN)} or {@code Infinite}, {@code false} otherwise. * * @param number number * @return Returns {@code true} if this {@code Number} value is * a {@code Not-a-Number (NaN)} or {@code Infinite}, {@code false} otherwise. * @since 0.3.4 */ public static boolean isInfinityOrNaN(Number number) { if (number == null) return false; if (isFloat(number)) { double d = number.doubleValue(); return Double.isNaN(d) || Double.isInfinite(d); } return false; } /** * Convert {@code Number} to {@code BigDecimal} * * @param number number * @return BigDecimal * @since 0.3.4 */ public static BigDecimal toBigDecimal(Number number) { if (number == null) return null; if (isInfinityOrNaN(number)) throw new NumberFormatException("The `number` is NaN or Infinity, can't convert to BigDecimal"); return number instanceof BigDecimal ? (BigDecimal) number : (isDouble(number) ? BigDecimal.valueOf(number.doubleValue()) : new BigDecimal(number.toString())); // float 使用字符串更准确 } /** * Compares two Numbers * * @param n1 number1 * @param n2 number2 * @return
    *
  • {@code -2}: one of the two numbers is {@code null}; *
  • {@code -1}: number1 less than number2; *
  •  {@code 0}: number1 equal number2; *
  •  {@code 1}: number1 greater than number2. *
* @since 0.3.0 */ public static int compare(Number n1, Number n2) { if (G.hasNull(n1, n2)) return -2; if (n1 == n2) return 0; boolean infinityOrNaN1 = isInfinityOrNaN(n1); boolean infinityOrNaN2 = isInfinityOrNaN(n2); if (infinityOrNaN1 || infinityOrNaN2) { if (infinityOrNaN1) { double d1 = n1.doubleValue(); if (infinityOrNaN2) { // infinityOrNaN1 为 true 且 infinityOrNaN2 为 true return Double.compare(d1, n2.doubleValue()); } else { // infinityOrNaN1 为 true,但 infinityOrNaN2 为 false if (Double.isNaN(d1) || d1 == Double.POSITIVE_INFINITY) { return 1; } else { return -1; } } } else { // infinityOrNaN1 为 false,但 infinityOrNaN2 为 true double d2 = n2.doubleValue(); if (Double.isNaN(d2) || d2 == Double.POSITIVE_INFINITY) { return -1; } else { return 1; } } } return toBigDecimal(n1).compareTo(toBigDecimal(n2)); } /** * Getting index of maximum value in {@link Number} array. * * @param numbers {@link Number} array * @return index of maximum value, {@code -1} if not found. * @since 0.3.0 */ public static int indexOfMax(Number[] numbers) { if (G.isEmpty(numbers)) return -1; int index = -1; Number max = null; for (int i = 0; i < numbers.length; i++) { Number number = numbers[i]; if (number != null) { if (max == null) { max = number; index = i; } else { if (compare(number, max) == 1) { max = number; index = i; } } } } return index; } /** * Getting index of minimum value in {@link Number} array. * * @param numbers {@link Number} array * @return index of minimum value, {@code -1} if not found. * @since 0.3.0 */ public static int indexOfMin(Number[] numbers) { if (G.isEmpty(numbers)) return -1; int index = -1; Number min = null; for (int i = 0; i < numbers.length; i++) { Number number = numbers[i]; if (number != null) { if (min == null) { min = number; index = i; } else { if (compare(number, min) == -1) { min = number; index = i; } } } } return index; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy