fix equlas

This commit is contained in:
Looly
2019-12-30 07:15:07 +08:00
parent d7316b3f90
commit 5e7b9012ec
17 changed files with 441 additions and 382 deletions

View File

@@ -10,6 +10,8 @@
* 【core 】 增加Convert.toPrimitiveByteArray方法Convert支持对象序列化和反序列化 * 【core 】 增加Convert.toPrimitiveByteArray方法Convert支持对象序列化和反序列化
* 【core 】 DateUtil增加isExpired(Date startDate, Date endDate, Date checkDate)issue#687@Github * 【core 】 DateUtil增加isExpired(Date startDate, Date endDate, Date checkDate)issue#687@Github
* 【core 】 增加Alias注解 * 【core 】 增加Alias注解
* 【core 】 修正NumberChineseFormatter和NumberWordFormatter类名拼写错误
* 【all 】 修正equals避免可能存在的空指针问题pr#692@Github
### Bug修复 ### Bug修复

View File

@@ -922,7 +922,7 @@ public class Convert {
* @since 3.0.9 * @since 3.0.9
*/ */
public static String numberToWord(Number number) { public static String numberToWord(Number number) {
return NumberWordFormater.format(number); return NumberWordFormatter.format(number);
} }
/** /**
@@ -934,7 +934,7 @@ public class Convert {
* @since 3.2.3 * @since 3.2.3
*/ */
public static String numberToChinese(double number, boolean isUseTraditonal) { public static String numberToChinese(double number, boolean isUseTraditonal) {
return NumberChineseFormater.format(number, isUseTraditonal); return NumberChineseFormatter.format(number, isUseTraditonal);
} }
/** /**
@@ -948,7 +948,7 @@ public class Convert {
if(null == n) { if(null == n) {
return ""; return "";
} }
return NumberChineseFormater.format(n.doubleValue(), true, true); return NumberChineseFormatter.format(n.doubleValue(), true, true);
} }
// -------------------------------------------------------------------------- 数字转换 // -------------------------------------------------------------------------- 数字转换

View File

@@ -1,7 +1,5 @@
package cn.hutool.core.convert; package cn.hutool.core.convert;
import cn.hutool.core.util.StrUtil;
/** /**
* 数字转中文类<br> * 数字转中文类<br>
* 包括: * 包括:
@@ -11,162 +9,9 @@ import cn.hutool.core.util.StrUtil;
* 3. 转金额形式,比如:壹佰贰拾壹整 * 3. 转金额形式,比如:壹佰贰拾壹整
* </pre> * </pre>
* *
* @author fanqun,looly * @author fanqun, looly
* @deprecated 请使用 {@link NumberChineseFormatter}
**/ **/
public class NumberChineseFormater { @Deprecated
public class NumberChineseFormater extends NumberChineseFormatter{
/** 简体中文形式 **/
private static final String[] simpleDigits = { "", "", "", "", "", "", "", "", "", "" };
/** 繁体中文形式 **/
private static final String[] traditionalDigits = { "", "", "", "", "", "", "", "", "", "" };
/** 简体中文单位 **/
private static final String[] simpleUnits = { "", "", "", "" };
/** 繁体中文单位 **/
private static final String[] traditionalUnits = { "", "", "", "" };
/**
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数、小数的转换.
*
* @param amount 数字
* @param isUseTraditional 是否使用繁体
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional) {
return format(amount, isUseTraditional, false);
}
/**
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数、小数的转换.
*
* @param amount 数字
* @param isUseTraditional 是否使用繁体
* @param isMoneyMode 是否为金额模式
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) {
final String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
if (amount > 99999999999999.99 || amount < -99999999999999.99) {
throw new IllegalArgumentException("Number support only: (-99999999999999.99 99999999999999.99)");
}
boolean negative = false;
if (amount < 0) {
negative = true;
amount = - amount;
}
long temp = Math.round(amount * 100);
int numFen = (int) (temp % 10);
temp = temp / 10;
int numJiao = (int) (temp % 10);
temp = temp / 10;
//将数字以万为单位分为多份
int[] parts = new int[20];
int numParts = 0;
for (int i = 0; temp != 0; i++) {
int part = (int) (temp % 10000);
parts[i] = part;
numParts++;
temp = temp / 10000;
}
boolean beforeWanIsZero = true; // 标志“万”下面一级是不是 0
String chineseStr = StrUtil.EMPTY;
for (int i = 0; i < numParts; i++) {
String partChinese = toChinese(parts[i], isUseTraditional);
if (i % 2 == 0) {
beforeWanIsZero = StrUtil.isEmpty(partChinese);
}
if (i != 0) {
if (i % 2 == 0) {
chineseStr = "亿" + chineseStr;
} else {
if ("".equals(partChinese) && false == beforeWanIsZero) {
// 如果“万”对应的 part 为 0而“万”下面一级不为 0则不加“万”而加“零”
chineseStr = "" + chineseStr;
} else {
if (parts[i - 1] < 1000 && parts[i - 1] > 0) {
// 如果"万"的部分不为 0, 而"万"前面的部分小于 1000 大于 0 则万后面应该跟“零”
chineseStr = "" + chineseStr;
}
chineseStr = "" + chineseStr;
}
}
}
chineseStr = partChinese + chineseStr;
}
// 整数部分为 0, 则表达为"零"
if (StrUtil.EMPTY.equals(chineseStr)) {
chineseStr = numArray[0];
}
//负数
if (negative) { // 整数部分不为 0
chineseStr = "" + chineseStr;
}
// 小数部分
if (numFen != 0 || numJiao != 0) {
if (numFen == 0) {
chineseStr += (isMoneyMode ? "" : "") + numArray[numJiao] + (isMoneyMode ? "" : "");
} else { // “分”数不为 0
if (numJiao == 0) {
chineseStr += (isMoneyMode ? "元零" : "点零") + numArray[numFen] + (isMoneyMode ? "" : "");
} else {
chineseStr += (isMoneyMode ? "" : "") + numArray[numJiao] + (isMoneyMode ? "" : "") + numArray[numFen] + (isMoneyMode ? "" : "");
}
}
}else if(isMoneyMode) {
//无小数部分的金额结尾
chineseStr += "元整";
}
return chineseStr;
}
/**
* 把一个 0~9999 之间的整数转换为汉字的字符串,如果是 0 则返回 ""
*
* @param amountPart 数字部分
* @param isUseTraditional 是否使用繁体单位
* @return 转换后的汉字
*/
private static String toChinese(int amountPart, boolean isUseTraditional) {
// if (amountPart < 0 || amountPart > 10000) {
// throw new IllegalArgumentException("Number must 0 < num < 10000");
// }
String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
String[] units = isUseTraditional ? traditionalUnits : simpleUnits;
int temp = amountPart;
String chineseStr = "";
boolean lastIsZero = true; // 在从低位往高位循环时,记录上一位数字是不是 0
for (int i = 0; temp > 0; i++) {
if (temp == 0) {
// 高位已无数据
break;
}
int digit = temp % 10;
if (digit == 0) { // 取到的数字为 0
if (false == lastIsZero) {
// 前一个数字不是 0则在当前汉字串前加“零”字;
chineseStr = "" + chineseStr;
}
lastIsZero = true;
} else { // 取到的数字不是 0
chineseStr = numArray[digit] + units[i] + chineseStr;
lastIsZero = false;
}
temp = temp / 10;
}
return chineseStr;
}
} }

View File

@@ -0,0 +1,176 @@
package cn.hutool.core.convert;
import cn.hutool.core.util.StrUtil;
/**
* 数字转中文类<br>
* 包括:
* <pre>
* 1. 数字转中文大写形式,比如一百二十一
* 2. 数字转金额用的大写形式,比如:壹佰贰拾壹
* 3. 转金额形式,比如:壹佰贰拾壹整
* </pre>
*
* @author fanqun, looly
**/
public class NumberChineseFormatter {
/**
* 简体中文形式
**/
private static final String[] simpleDigits = {"", "", "", "", "", "", "", "", "", ""};
/**
* 繁体中文形式
**/
private static final String[] traditionalDigits = {"", "", "", "", "", "", "", "", "", ""};
/**
* 简体中文单位
**/
private static final String[] simpleUnits = {"", "", "", ""};
/**
* 繁体中文单位
**/
private static final String[] traditionalUnits = {"", "", "", ""};
/**
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数、小数的转换.
*
* @param amount 数字
* @param isUseTraditional 是否使用繁体
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional) {
return format(amount, isUseTraditional, false);
}
/**
* 阿拉伯数字转换成中文,小数点后四舍五入保留两位. 使用于整数、小数的转换.
*
* @param amount 数字
* @param isUseTraditional 是否使用繁体
* @param isMoneyMode 是否为金额模式
* @return 中文
*/
public static String format(double amount, boolean isUseTraditional, boolean isMoneyMode) {
final String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
if (amount > 99999999999999.99 || amount < -99999999999999.99) {
throw new IllegalArgumentException("Number support only: (-99999999999999.99 99999999999999.99)");
}
boolean negative = false;
if (amount < 0) {
negative = true;
amount = -amount;
}
long temp = Math.round(amount * 100);
int numFen = (int) (temp % 10);
temp = temp / 10;
int numJiao = (int) (temp % 10);
temp = temp / 10;
//将数字以万为单位分为多份
int[] parts = new int[20];
int numParts = 0;
for (int i = 0; temp != 0; i++) {
int part = (int) (temp % 10000);
parts[i] = part;
numParts++;
temp = temp / 10000;
}
boolean beforeWanIsZero = true; // 标志“万”下面一级是不是 0
StringBuilder chineseStr = new StringBuilder();
for (int i = 0; i < numParts; i++) {
String partChinese = toChinese(parts[i], isUseTraditional);
if (i % 2 == 0) {
beforeWanIsZero = StrUtil.isEmpty(partChinese);
}
if (i != 0) {
if (i % 2 == 0) {
chineseStr.insert(0, "亿");
} else {
if ("".equals(partChinese) && false == beforeWanIsZero) {
// 如果“万”对应的 part 为 0而“万”下面一级不为 0则不加“万”而加“零”
chineseStr.insert(0, "");
} else {
if (parts[i - 1] < 1000 && parts[i - 1] > 0) {
// 如果"万"的部分不为 0, 而"万"前面的部分小于 1000 大于 0 则万后面应该跟“零”
chineseStr.insert(0, "");
}
chineseStr.insert(0, "");
}
}
}
chineseStr.insert(0, partChinese);
}
// 整数部分为 0, 则表达为"零"
if (StrUtil.EMPTY.equals(chineseStr.toString())) {
chineseStr = new StringBuilder(numArray[0]);
}
//负数
if (negative) { // 整数部分不为 0
chineseStr.insert(0, "");
}
// 小数部分
if (numFen != 0 || numJiao != 0) {
if (numFen == 0) {
chineseStr.append(isMoneyMode ? "" : "").append(numArray[numJiao]).append(isMoneyMode ? "" : "");
} else { // “分”数不为 0
if (numJiao == 0) {
chineseStr.append(isMoneyMode ? "元零" : "点零").append(numArray[numFen]).append(isMoneyMode ? "" : "");
} else {
chineseStr.append(isMoneyMode ? "" : "").append(numArray[numJiao]).append(isMoneyMode ? "" : "").append(numArray[numFen]).append(isMoneyMode ? "" : "");
}
}
} else if (isMoneyMode) {
//无小数部分的金额结尾
chineseStr.append("元整");
}
return chineseStr.toString();
}
/**
* 把一个 0~9999 之间的整数转换为汉字的字符串,如果是 0 则返回 ""
*
* @param amountPart 数字部分
* @param isUseTraditional 是否使用繁体单位
* @return 转换后的汉字
*/
private static String toChinese(int amountPart, boolean isUseTraditional) {
// if (amountPart < 0 || amountPart > 10000) {
// throw new IllegalArgumentException("Number must 0 < num < 10000");
// }
String[] numArray = isUseTraditional ? traditionalDigits : simpleDigits;
String[] units = isUseTraditional ? traditionalUnits : simpleUnits;
int temp = amountPart;
StringBuilder chineseStr = new StringBuilder();
boolean lastIsZero = true; // 在从低位往高位循环时,记录上一位数字是不是 0
for (int i = 0; temp > 0; i++) {
int digit = temp % 10;
if (digit == 0) { // 取到的数字为 0
if (false == lastIsZero) {
// 前一个数字不是 0则在当前汉字串前加“零”字;
chineseStr.insert(0, "");
}
lastIsZero = true;
} else { // 取到的数字不是 0
chineseStr.insert(0, numArray[digit] + units[i]);
lastIsZero = false;
}
temp = temp / 10;
}
return chineseStr.toString();
}
}

View File

@@ -1,146 +1,14 @@
package cn.hutool.core.convert; package cn.hutool.core.convert;
import cn.hutool.core.util.StrUtil;
import java.util.Objects;
/** /**
* 将浮点数类型的number转换成英语的表达方式 <br> * 将浮点数类型的number转换成英语的表达方式 <br>
* 参考博客http://blog.csdn.net/eric_sunah/article/details/8713226 * 参考博客http://blog.csdn.net/eric_sunah/article/details/8713226
* *
* @author Looly * @author Looly
* @since 3.0.9 * @since 3.0.9
* @see <a href= * @deprecated 请使用 {@link NumberWordFormatter}
* "http://blog.csdn.net/eric_sunah/article/details/8713226">http://blog.csdn.net/eric_sunah/article/details/8713226</a>
*/ */
public class NumberWordFormater { @Deprecated
public class NumberWordFormater extends NumberWordFormatter{
private static final String[] NUMBER = new String[] { "", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
"EIGHT", "NINE" };
private static final String[] NUMBER_TEEN = new String[] { "TEN", "ELEVEN", "TWELEVE", "THIRTEEN", "FOURTEEN",
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN" };
private static final String[] NUMBER_TEN = new String[] { "TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
"SEVENTY", "EIGHTY", "NINETY" };
private static final String[] NUMBER_MORE = new String[] { "", "THOUSAND", "MILLION", "BILLION" };
/**
* 将阿拉伯数字转为英文表达式
*
* @param x
* 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
* @return 英文表达式
*/
public static String format(Object x) {
if (x != null) {
return format(x.toString());
} else {
return "";
}
}
/**
* 将阿拉伯数字转为英文表达式
*
* @param x
* 阿拉伯数字字符串
* @return 英文表达式
*/
private static String format(String x) {
int z = x.indexOf("."); // 取小数点位置
String lstr, rstr = "";
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
lstr = x.substring(0, z);
rstr = x.substring(z + 1);
} else {
// 否则就是全部
lstr = x;
}
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
switch (lstrrev.length() % 3) {
case 1:
lstrrev += "00";
break;
case 2:
lstrrev += "0";
break;
}
StringBuilder lm = new StringBuilder(); // 用来存放转换後的整数部分
for (int i = 0; i < lstrrev.length() / 3; i++) {
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个叁位
if (!Objects.equals(a[i],"000")) { // 用来避免这种情况1000000 = one million
// thousand only
if (i != 0) {
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
// thousand、million、billion
} else {
// 防止i=0时 在多加两个空格.
lm = new StringBuilder(transThree(a[i]));
}
} else {
lm.append(transThree(a[i]));
}
}
String xs = ""; // 用来存放转换後小数部分
if (z > -1) {
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
}
return lm.toString().trim() + " " + xs + "ONLY";
}
private static String parseFirst(String s) {
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
}
private static String parseTeen(String s) {
return NUMBER_TEEN[Integer.parseInt(s) - 10];
}
private static String parseTen(String s) {
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
}
private static String parseMore(int i) {
return NUMBER_MORE[i];
}
// 两位
private static String transTwo(String s) {
String value;
// 判断位数
if (s.length() > 2) {
s = s.substring(0, 2);
} else if (s.length() < 2) {
s = "0" + s;
}
if (s.startsWith("0")) {// 07 - seven 是否小於10
value = parseFirst(s);
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
value = parseTeen(s);
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
value = parseTen(s);
} else {
value = parseTen(s) + " " + parseFirst(s);
}
return value;
}
// 制作叁位的数
// s.length = 3
private static String transThree(String s) {
String value;
if (s.startsWith("0")) {// 是否小於100
value = transTwo(s.substring(1));
} else if (Objects.equals(s.substring(1),"00")) {// 是否被100整除
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
} else {
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
}
return value;
}
} }

View File

@@ -0,0 +1,140 @@
package cn.hutool.core.convert;
import cn.hutool.core.util.StrUtil;
/**
* 将浮点数类型的number转换成英语的表达方式 <br>
* 参考博客http://blog.csdn.net/eric_sunah/article/details/8713226
*
* @author Looly
* @since 3.0.9
*/
public class NumberWordFormatter {
private static final String[] NUMBER = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN",
"EIGHT", "NINE"};
private static final String[] NUMBER_TEEN = new String[]{"TEN", "ELEVEN", "TWELEVE", "THIRTEEN", "FOURTEEN",
"FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
private static final String[] NUMBER_TEN = new String[]{"TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY",
"SEVENTY", "EIGHTY", "NINETY"};
private static final String[] NUMBER_MORE = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
/**
* 将阿拉伯数字转为英文表达式
*
* @param x 阿拉伯数字,可以为{@link Number}对象,也可以是普通对象,最后会使用字符串方式处理
* @return 英文表达式
*/
public static String format(Object x) {
if (x != null) {
return format(x.toString());
} else {
return "";
}
}
/**
* 将阿拉伯数字转为英文表达式
*
* @param x 阿拉伯数字字符串
* @return 英文表达式
*/
private static String format(String x) {
int z = x.indexOf("."); // 取小数点位置
String lstr, rstr = "";
if (z > -1) { // 看是否有小数,如果有,则分别取左边和右边
lstr = x.substring(0, z);
rstr = x.substring(z + 1);
} else {
// 否则就是全部
lstr = x;
}
String lstrrev = StrUtil.reverse(lstr); // 对左边的字串取反
String[] a = new String[5]; // 定义5个字串变量来存放解析出来的叁位一组的字串
switch (lstrrev.length() % 3) {
case 1:
lstrrev += "00";
break;
case 2:
lstrrev += "0";
break;
}
StringBuilder lm = new StringBuilder(); // 用来存放转换后的整数部分
for (int i = 0; i < lstrrev.length() / 3; i++) {
a[i] = StrUtil.reverse(lstrrev.substring(3 * i, 3 * i + 3)); // 截取第一个三位
if (false == "000".equals(a[i])) { // 用来避免这种情况1000000 = one million
// thousand only
if (i != 0) {
lm.insert(0, transThree(a[i]) + " " + parseMore(i) + " "); // 加:
// thousand、million、billion
} else {
// 防止i=0时 在多加两个空格.
lm = new StringBuilder(transThree(a[i]));
}
} else {
lm.append(transThree(a[i]));
}
}
String xs = ""; // 用来存放转换后小数部分
if (z > -1) {
xs = "AND CENTS " + transTwo(rstr) + " "; // 小数部分存在时转换小数
}
return lm.toString().trim() + " " + xs + "ONLY";
}
private static String parseFirst(String s) {
return NUMBER[Integer.parseInt(s.substring(s.length() - 1))];
}
private static String parseTeen(String s) {
return NUMBER_TEEN[Integer.parseInt(s) - 10];
}
private static String parseTen(String s) {
return NUMBER_TEN[Integer.parseInt(s.substring(0, 1)) - 1];
}
private static String parseMore(int i) {
return NUMBER_MORE[i];
}
// 两位
private static String transTwo(String s) {
String value;
// 判断位数
if (s.length() > 2) {
s = s.substring(0, 2);
} else if (s.length() < 2) {
s = "0" + s;
}
if (s.startsWith("0")) {// 07 - seven 是否小於10
value = parseFirst(s);
} else if (s.startsWith("1")) {// 17 seventeen 是否在10和20之间
value = parseTeen(s);
} else if (s.endsWith("0")) {// 是否在10与100之间的能被10整除的数
value = parseTen(s);
} else {
value = parseTen(s) + " " + parseFirst(s);
}
return value;
}
// 制作叁位的数
// s.length = 3
private static String transThree(String s) {
String value;
if (s.startsWith("0")) {// 是否小於100
value = transTwo(s.substring(1));
} else if ("00".equals(s.substring(1))) {// 是否被100整除
value = parseFirst(s.substring(0, 1)) + " HUNDRED";
} else {
value = parseFirst(s.substring(0, 1)) + " HUNDRED AND " + transTwo(s.substring(1));
}
return value;
}
}

View File

@@ -5,7 +5,19 @@ import java.io.ObjectInputStream;
import java.text.DateFormatSymbols; import java.text.DateFormatSymbols;
import java.text.ParseException; import java.text.ParseException;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.util.*; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -15,15 +27,17 @@ import java.util.regex.Pattern;
* {@link java.text.SimpleDateFormat} 的线程安全版本,用于解析日期字符串并转换为 {@link Date} 对象<br> * {@link java.text.SimpleDateFormat} 的线程安全版本,用于解析日期字符串并转换为 {@link Date} 对象<br>
* Thanks to Apache Commons Lang 3.5 * Thanks to Apache Commons Lang 3.5
* *
* @since 2.16.2
* @see FastDatePrinter * @see FastDatePrinter
* @since 2.16.2
*/ */
class FastDateParser extends AbstractDateBasic implements DateParser { class FastDateParser extends AbstractDateBasic implements DateParser {
private static final long serialVersionUID = -3199383897950947498L; private static final long serialVersionUID = -3199383897950947498L;
static final Locale JAPANESE_IMPERIAL = new Locale("ja", "JP", "JP"); static final Locale JAPANESE_IMPERIAL = new Locale("ja", "JP", "JP");
/** 世纪2000年前为19 之后为20 */ /**
* 世纪2000年前为19 之后为20
*/
private final int century; private final int century;
private final int startYear; private final int startYear;
@@ -33,13 +47,13 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
// comparator used to sort regex alternatives // comparator used to sort regex alternatives
// alternatives should be ordered longer first, and shorter last. ('february' before 'feb') // alternatives should be ordered longer first, and shorter last. ('february' before 'feb')
// all entries must be lowercase by locale. // all entries must be lowercase by locale.
private static final Comparator<String> LONGER_FIRST_LOWERCASE = (left, right) -> right.compareTo(left); private static final Comparator<String> LONGER_FIRST_LOWERCASE = Comparator.reverseOrder();
/** /**
* <p> * <p>
* Constructs a new FastDateParser. * Constructs a new FastDateParser.
* </p> * </p>
* * <p>
* Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)} or another variation of the factory methods of {@link FastDateFormat} to get a cached FastDateParser instance. * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)} or another variation of the factory methods of {@link FastDateFormat} to get a cached FastDateParser instance.
* *
* @param pattern non-null {@link java.text.SimpleDateFormat} compatible pattern * @param pattern non-null {@link java.text.SimpleDateFormat} compatible pattern
@@ -90,7 +104,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
patterns = new ArrayList<>(); patterns = new ArrayList<>();
final StrategyParser fm = new StrategyParser(definingCalendar); final StrategyParser fm = new StrategyParser(definingCalendar);
for (;;) { for (; ; ) {
final StrategyAndWidth field = fm.getNextStrategy(); final StrategyAndWidth field = fm.getNextStrategy();
if (field == null) { if (field == null) {
break; break;
@@ -190,6 +204,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
// Serializing // Serializing
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
/** /**
* Create the object after serialization. This implementation reinitializes the transient properties. * Create the object after serialization. This implementation reinitializes the transient properties.
* *
@@ -538,13 +553,10 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
createPattern(regex); createPattern(regex);
} }
/**
* {@inheritDoc}
*/
@Override @Override
void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { void setCalendar(final FastDateParser parser, final Calendar cal, final String value) {
final Integer iVal = lKeyValues.get(value.toLowerCase(locale)); final Integer iVal = lKeyValues.get(value.toLowerCase(locale));
cal.set(field, iVal.intValue()); cal.set(field, iVal);
} }
} }
@@ -624,7 +636,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
} }
private static final Strategy ABBREVIATED_YEAR_STRATEGY = new NumberStrategy(Calendar.YEAR){ private static final Strategy ABBREVIATED_YEAR_STRATEGY = new NumberStrategy(Calendar.YEAR) {
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@@ -750,7 +762,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
*/ */
@Override @Override
void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { void setCalendar(final FastDateParser parser, final Calendar cal, final String value) {
if (Objects.equals(value,"Z")) { if (Objects.equals(value, "Z")) {
cal.setTimeZone(TimeZone.getTimeZone("UTC")); cal.setTimeZone(TimeZone.getTimeZone("UTC"));
} else { } else {
cal.setTimeZone(TimeZone.getTimeZone("GMT" + value)); cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
@@ -781,7 +793,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
} }
} }
private static final Strategy NUMBER_MONTH_STRATEGY = new NumberStrategy(Calendar.MONTH){ private static final Strategy NUMBER_MONTH_STRATEGY = new NumberStrategy(Calendar.MONTH) {
@Override @Override
int modify(final FastDateParser parser, final int iValue) { int modify(final FastDateParser parser, final int iValue) {
return iValue - 1; return iValue - 1;
@@ -792,7 +804,7 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
private static final Strategy WEEK_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_MONTH); private static final Strategy WEEK_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_MONTH);
private static final Strategy DAY_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.DAY_OF_YEAR); private static final Strategy DAY_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.DAY_OF_YEAR);
private static final Strategy DAY_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_MONTH); private static final Strategy DAY_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_MONTH);
private static final Strategy DAY_OF_WEEK_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK){ private static final Strategy DAY_OF_WEEK_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK) {
@Override @Override
int modify(final FastDateParser parser, final int iValue) { int modify(final FastDateParser parser, final int iValue) {
return iValue != 7 ? iValue + 1 : Calendar.SUNDAY; return iValue != 7 ? iValue + 1 : Calendar.SUNDAY;
@@ -800,13 +812,13 @@ class FastDateParser extends AbstractDateBasic implements DateParser {
}; };
private static final Strategy DAY_OF_WEEK_IN_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK_IN_MONTH); private static final Strategy DAY_OF_WEEK_IN_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK_IN_MONTH);
private static final Strategy HOUR_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY); private static final Strategy HOUR_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY);
private static final Strategy HOUR24_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY){ private static final Strategy HOUR24_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY) {
@Override @Override
int modify(final FastDateParser parser, final int iValue) { int modify(final FastDateParser parser, final int iValue) {
return iValue == 24 ? 0 : iValue; return iValue == 24 ? 0 : iValue;
} }
}; };
private static final Strategy HOUR12_STRATEGY = new NumberStrategy(Calendar.HOUR){ private static final Strategy HOUR12_STRATEGY = new NumberStrategy(Calendar.HOUR) {
@Override @Override
int modify(final FastDateParser parser, final int iValue) { int modify(final FastDateParser parser, final int iValue) {
return iValue == 12 ? 0 : iValue; return iValue == 12 ? 0 : iValue;

View File

@@ -174,8 +174,8 @@ public class IdcardUtil {
case 15:// 15位身份证 case 15:// 15位身份证
return isValidCard15(idCard); return isValidCard15(idCard);
case 10: {// 10位身份证港澳台地区 case 10: {// 10位身份证港澳台地区
String[] cardval = isValidCard10(idCard); String[] cardVal = isValidCard10(idCard);
return null != cardval && Objects.equals(cardval[2],"true"); return null != cardVal && "true".equals(cardVal[2]);
} }
default: default:
return false; return false;
@@ -279,10 +279,10 @@ public class IdcardUtil {
} }
if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾 if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾
info[0] = "台湾"; info[0] = "台湾";
String char2 = idCard.substring(1, 2); char char2 = idCard.charAt(1);
if (Objects.equals(char2,"1")) { if ('1' == char2) {
info[1] = "M"; info[1] = "M";
} else if (Objects.equals(char2,"2")) { } else if ('2' == char2) {
info[1] = "F"; info[1] = "F";
} else { } else {
info[1] = "N"; info[1] = "N";

View File

@@ -48,7 +48,7 @@ public class ReferenceUtil {
case WEAK: case WEAK:
return new WeakReference<>(referent); return new WeakReference<>(referent);
case PHANTOM: case PHANTOM:
return new PhantomReference<T>(referent, queue); return new PhantomReference<>(referent, queue);
default: default:
return null; return null;
} }

View File

@@ -12,7 +12,12 @@ import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/** /**
* 反射工具类 * 反射工具类
@@ -138,7 +143,7 @@ public class ReflectUtil {
* @return 字段名和字段对应的Map * @return 字段名和字段对应的Map
* @since 5.0.7 * @since 5.0.7
*/ */
public static Map<String, Field> getFieldMap(Class<?> beanClass){ public static Map<String, Field> getFieldMap(Class<?> beanClass) {
final Field[] fields = getFields(beanClass); final Field[] fields = getFields(beanClass);
final HashMap<String, Field> map = MapUtil.newHashMap(fields.length); final HashMap<String, Field> map = MapUtil.newHashMap(fields.length);
for (Field field : fields) { for (Field field : fields) {
@@ -203,7 +208,7 @@ public class ReflectUtil {
if (null == obj || StrUtil.isBlank(fieldName)) { if (null == obj || StrUtil.isBlank(fieldName)) {
return null; return null;
} }
return getFieldValue(obj, getField(obj instanceof Class ? (Class<?>)obj : obj.getClass(), fieldName)); return getFieldValue(obj, getField(obj instanceof Class ? (Class<?>) obj : obj.getClass(), fieldName));
} }
/** /**
@@ -230,7 +235,7 @@ public class ReflectUtil {
if (null == field) { if (null == field) {
return null; return null;
} }
if(obj instanceof Class){ if (obj instanceof Class) {
// 静态字段获取时对象为null // 静态字段获取时对象为null
obj = null; obj = null;
} }
@@ -254,7 +259,7 @@ public class ReflectUtil {
*/ */
public static Object[] getFieldsValue(Object obj) { public static Object[] getFieldsValue(Object obj) {
if (null != obj) { if (null != obj) {
final Field[] fields = getFields(obj instanceof Class ? (Class<?>)obj : obj.getClass()); final Field[] fields = getFields(obj instanceof Class ? (Class<?>) obj : obj.getClass());
if (null != fields) { if (null != fields) {
final Object[] values = new Object[fields.length]; final Object[] values = new Object[fields.length];
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
@@ -647,7 +652,7 @@ public class ReflectUtil {
* @return 是否为equals方法 * @return 是否为equals方法
*/ */
public static boolean isEqualsMethod(Method method) { public static boolean isEqualsMethod(Method method) {
if (method == null || false == Objects.equals(method.getName(),"equals")) { if (method == null || false == "equals".equals(method.getName())) {
return false; return false;
} }
final Class<?>[] paramTypes = method.getParameterTypes(); final Class<?>[] paramTypes = method.getParameterTypes();
@@ -661,7 +666,9 @@ public class ReflectUtil {
* @return 是否为hashCode方法 * @return 是否为hashCode方法
*/ */
public static boolean isHashCodeMethod(Method method) { public static boolean isHashCodeMethod(Method method) {
return (method != null && Objects.equals(method.getName(),"hashCode") && method.getParameterTypes().length == 0); return method != null//
&& "hashCode".equals(method.getName())//
&& isEmptyParam(method);
} }
/** /**
@@ -671,7 +678,20 @@ public class ReflectUtil {
* @return 是否为toString方法 * @return 是否为toString方法
*/ */
public static boolean isToStringMethod(Method method) { public static boolean isToStringMethod(Method method) {
return (method != null && Objects.equals(method.getName(),"toString") && method.getParameterTypes().length == 0); return method != null//
&& "toString".equals(method.getName())//
&& isEmptyParam(method);
}
/**
* 是否为无参数方法
*
* @param method 方法
* @return 是否为无参数方法
* @since 5.1.1
*/
public static boolean isEmptyParam(Method method) {
return method.getParameterTypes().length == 0;
} }
// --------------------------------------------------------------------------------------------------------- newInstance // --------------------------------------------------------------------------------------------------------- newInstance

View File

@@ -2,8 +2,6 @@ package cn.hutool.cron.pattern.parser;
import cn.hutool.cron.CronException; import cn.hutool.cron.CronException;
import java.util.Objects;
/** /**
* 每月的几号值处理<br> * 每月的几号值处理<br>
* 每月最多31天32和“L”都表示最后一天 * 每月最多31天32和“L”都表示最后一天
@@ -19,7 +17,7 @@ public class DayOfMonthValueParser extends SimpleValueParser {
@Override @Override
public int parse(String value) throws CronException { public int parse(String value) throws CronException {
if ("L".equalsIgnoreCase(value) || Objects.equals("32",value)) {// 每月最后一天 if ("L".equalsIgnoreCase(value) || "32".equals(value)) {// 每月最后一天
return 32; return 32;
} else { } else {
return super.parse(value); return super.parse(value);

View File

@@ -176,6 +176,7 @@ public class Db extends AbstractDb {
final int level = transactionLevel.getLevel(); final int level = transactionLevel.getLevel();
if (conn.getTransactionIsolation() < level) { if (conn.getTransactionIsolation() < level) {
// 用户定义的事务级别如果比默认级别更严格,则按照严格的级别进行 // 用户定义的事务级别如果比默认级别更严格,则按照严格的级别进行
//noinspection MagicConstant
conn.setTransactionIsolation(level); conn.setTransactionIsolation(level);
} }
} }

View File

@@ -126,7 +126,7 @@ public class SqlFormatter {
values(); values();
} else if ("on".equals(this.lcToken)) { } else if ("on".equals(this.lcToken)) {
on(); on();
} else if ((this.afterBetween) && (Objects.equals(this.lcToken,"and"))) { } else if ((this.afterBetween) && ("and".equals(this.lcToken))) {
misc(); misc();
this.afterBetween = false; this.afterBetween = false;
} else if (LOGICAL.contains(this.lcToken)) { } else if (LOGICAL.contains(this.lcToken)) {
@@ -213,8 +213,8 @@ public class SqlFormatter {
out(); out();
this.indent += 1; this.indent += 1;
newline(); newline();
this.parenCounts.addLast(new Integer(this.parensSinceSelect)); this.parenCounts.addLast(this.parensSinceSelect);
this.afterByOrFromOrSelects.addLast(Boolean.valueOf(this.afterByOrSetOrFromOrSelect)); this.afterByOrFromOrSelects.addLast(this.afterByOrSetOrFromOrSelect);
this.parensSinceSelect = 0; this.parensSinceSelect = 0;
this.afterByOrSetOrFromOrSelect = true; this.afterByOrSetOrFromOrSelect = true;
} }
@@ -268,8 +268,8 @@ public class SqlFormatter {
this.parensSinceSelect -= 1; this.parensSinceSelect -= 1;
if (this.parensSinceSelect < 0) { if (this.parensSinceSelect < 0) {
this.indent -= 1; this.indent -= 1;
this.parensSinceSelect = ((Integer) this.parenCounts.removeLast()).intValue(); this.parensSinceSelect = this.parenCounts.removeLast();
this.afterByOrSetOrFromOrSelect = ((Boolean) this.afterByOrFromOrSelects.removeLast()).booleanValue(); this.afterByOrSetOrFromOrSelect = this.afterByOrFromOrSelects.removeLast();
} }
if (this.inFunction > 0) { if (this.inFunction > 0) {
this.inFunction -= 1; this.inFunction -= 1;

View File

@@ -1,5 +1,14 @@
package cn.hutool.extra.ftp; package cn.hutool.extra.ftp;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -7,17 +16,6 @@ import java.io.OutputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
/** /**
* FTP客户端封装<br> * FTP客户端封装<br>
@@ -340,7 +338,7 @@ public class Ftp extends AbstractFtp {
childPath = StrUtil.format("{}/{}", dirPath, name); childPath = StrUtil.format("{}/{}", dirPath, name);
if (ftpFile.isDirectory()) { if (ftpFile.isDirectory()) {
// 上级和本级目录除外 // 上级和本级目录除外
if (false == Objects.equals(name,".") && false == Objects.equals(name,"..")) { if (false == ".".equals(name) && false == "..".equals(name)) {
delDir(childPath); delDir(childPath);
} }
} else { } else {

View File

@@ -15,7 +15,6 @@ import java.io.File;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Vector; import java.util.Vector;
/** /**
@@ -312,7 +311,7 @@ public class Sftp extends AbstractFtp {
String fileName; String fileName;
for (LsEntry entry : list) { for (LsEntry entry : list) {
fileName = entry.getFilename(); fileName = entry.getFilename();
if (false == Objects.equals(fileName,".") && false == Objects.equals(fileName,"..")) { if (false == ".".equals(fileName) && false == "..".equals(fileName)) {
if (entry.getAttrs().isDir()) { if (entry.getAttrs().isDir()) {
delDir(fileName); delDir(fileName);
} else { } else {

View File

@@ -381,7 +381,7 @@ public class HttpRequest extends HttpBase<HttpRequest> {
return !httpVersion.equalsIgnoreCase(HTTP_1_0); return !httpVersion.equalsIgnoreCase(HTTP_1_0);
} }
return !"close".equalsIgnoreCase(connection); return false == "close".equalsIgnoreCase(connection);
} }
/** /**