From 538874562d68b3316d7d376ecec20714ced32223 Mon Sep 17 00:00:00 2001 From: naooohu Date: Thu, 20 Jan 2022 01:28:58 +0800 Subject: [PATCH 01/43] =?UTF-8?q?add=20=E6=B7=BB=E5=8A=A0=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E4=B8=A4=E4=B8=AA=E6=97=A5=E6=9C=9F=E6=98=AF=E5=90=A6?= =?UTF-8?q?=E4=B8=BA=E4=B8=80=E5=91=A8=EF=BC=88=E5=9B=BD=E5=86=85=E4=B8=80?= =?UTF-8?q?=E5=91=A8=E7=9A=84=E5=BC=80=E5=A7=8B=E4=B8=BA=E5=91=A8=E4=B8=80?= =?UTF-8?q?=EF=BC=8C=E5=9B=BD=E5=A4=96=E4=B8=80=E5=91=A8=E7=9A=84=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=E4=B8=BA=E5=91=A8=E6=97=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/date/CalendarUtil.java | 16 +++++++++++ .../java/cn/hutool/core/date/DateUtil.java | 28 +++++++++++++++++++ .../cn/hutool/core/date/DateUtilTest.java | 11 ++++++++ 3 files changed, 55 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index a1e2f176b..774aabec5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -348,6 +348,22 @@ public class CalendarUtil { cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA); } + /** + * 比较两个日期是否为同一周 + * + * @param cal1 日期1 + * @param cal2 日期2 + * @return 是否为同一周 + */ + public static boolean isSameWeek(Calendar cal1, Calendar cal2) { + if (cal1 == null || cal2 == null) { + throw new IllegalArgumentException("The date must not be null"); + } + return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && + cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && + cal1.get(Calendar.DAY_OF_WEEK) == cal2.get(Calendar.DAY_OF_WEEK); + } + /** * 比较两个日期是否为同一月 * diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index 813fba971..066777c78 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -1586,6 +1586,34 @@ public class DateUtil extends CalendarUtil { return CalendarUtil.isSameDay(calendar(date1), calendar(date2)); } + /** + * 比较两个日期是否为同一周 + * + * @param date1 日期1 + * @param date2 日期2 + * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日 + * @return 是否为同一周 + */ + public static boolean isSameWeek(final Date date1, final Date date2, boolean isMon) { + if (date1 == null || date2 == null) { + throw new IllegalArgumentException("The date must not be null"); + } + Calendar calendar1 = calendar(date1); + Calendar calendar2 = calendar(date2); + if (isMon) { + calendar1.setFirstDayOfWeek(Calendar.MONDAY); + calendar1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + calendar2.setFirstDayOfWeek(Calendar.MONDAY); + calendar2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + } else { + calendar1.setFirstDayOfWeek(Calendar.SUNDAY); + calendar1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + calendar2.setFirstDayOfWeek(Calendar.SUNDAY); + calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + } + return CalendarUtil.isSameWeek(calendar1, calendar2); + } + /** * 比较两个日期是否为同一月 * diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 24e7321a8..ceab8fe7e 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1004,4 +1004,15 @@ public class DateUtilTest { final DateTime parse = DateUtil.parse("2021-12-01", DatePattern.NORM_DATE_FORMATTER); Assert.assertEquals("2021-12-01 00:00:00", parse.toString()); } + + @Test + public void test() { + // 周六与周日比较 + final boolean isSameWeek = DateUtil.isSameWeek(DateTime.of("2022-01-01", "yyyy-MM-dd"), DateTime.of("2022-01-02", "yyyy-MM-dd"), true); + Assert.assertTrue(isSameWeek); + // 周日与周一比较 + final boolean isSameWeek1 = DateUtil.isSameWeek(DateTime.of("2022-01-02", "yyyy-MM-dd"), DateTime.of("2022-01-03", "yyyy-MM-dd"), false); + Assert.assertTrue(isSameWeek1); + + } } From 4447bb18d420c9e5b36e50485a2502b99b7865ec Mon Sep 17 00:00:00 2001 From: tjh Date: Thu, 20 Jan 2022 16:28:08 +0800 Subject: [PATCH 02/43] =?UTF-8?q?=E6=96=B0=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E7=BB=84=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=A4=8D=E6=9D=82=E7=9A=84where=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/db/sql/ConditionGroup.java | 51 +++++++++++++++++++ .../cn/hutool/db/sql/ConditionGroupTest.java | 26 ++++++++++ 2 files changed, 77 insertions(+) create mode 100644 hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java create mode 100644 hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java new file mode 100644 index 000000000..33467287a --- /dev/null +++ b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java @@ -0,0 +1,51 @@ +package cn.hutool.db.sql; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; + +import java.util.List; + +/** + * 条件组
+ * 用于构建复杂where条件 + * + * @author tjh + */ +public class ConditionGroup extends Condition{ + /** + * 条件列表 + */ + private Condition[] conditions; + + /** + * 追加条件 + * + * @param conditions 条件列表 + */ + public void addConditions(Condition... conditions) { + if(null == this.conditions) { + this.conditions = conditions; + } else { + this.conditions = ArrayUtil.addAll(this.conditions, conditions); + } + } + + /** + * 将条件组转换为条件字符串,使用括号包裹,并回填占位符对应的参数值 + * + * @param paramValues 参数列表,用于回填占位符对应参数值 + * @return 条件字符串 + */ + @Override + public String toString(List paramValues) { + if (ArrayUtil.isEmpty(conditions)) return StrUtil.EMPTY; + + final StringBuilder conditionStrBuilder = StrUtil.builder(); + conditionStrBuilder.append("("); + // 将组内的条件构造为SQL,因为toString,会进行递归,处理所有的条件组 + conditionStrBuilder.append(ConditionBuilder.of(this.conditions).build(paramValues)); + conditionStrBuilder.append(")"); + + return conditionStrBuilder.toString(); + } +} diff --git a/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java new file mode 100644 index 000000000..3c48c2218 --- /dev/null +++ b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java @@ -0,0 +1,26 @@ +package cn.hutool.db.sql; + +import org.junit.Test; + +public class ConditionGroupTest { + @Test + public void ConditionGroupToStringTest() { + Condition condition1 = new Condition("a", "A"); + Condition condition2 = new Condition("b", "B"); + condition2.setLinkOperator(LogicalOperator.OR); + Condition condition3 = new Condition("c", "C"); + Condition condition4 = new Condition("d", "D"); + + ConditionGroup cg = new ConditionGroup(); + cg.addConditions(condition1, condition2); + + // 条件组嵌套情况 + ConditionGroup cg2 = new ConditionGroup(); + cg2.addConditions(cg, condition3); + + final ConditionBuilder conditionBuilder = ConditionBuilder.of(cg2, condition4); + + System.out.println(conditionBuilder.build()); + System.out.println(conditionBuilder.getParamValues()); + } +} From 7d4d87be829341c493d33e795bbbe1abda86e775 Mon Sep 17 00:00:00 2001 From: naooohu Date: Thu, 20 Jan 2022 21:12:29 +0800 Subject: [PATCH 03/43] =?UTF-8?q?add=20=E6=B7=BB=E5=8A=A0=E8=B7=A8?= =?UTF-8?q?=E6=9C=88=E6=AF=94=E8=BE=83=E6=98=AF=E5=90=A6=E5=9C=A8=E5=90=8C?= =?UTF-8?q?=E4=B8=80=E5=91=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/date/CalendarUtil.java | 4 +--- .../src/test/java/cn/hutool/core/date/DateUtilTest.java | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index 774aabec5..4c6d3093c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -359,9 +359,7 @@ public class CalendarUtil { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } - return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && - cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH) && - cal1.get(Calendar.DAY_OF_WEEK) == cal2.get(Calendar.DAY_OF_WEEK); + return isSameDay(cal1, cal2); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index ceab8fe7e..0aea526a6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -1006,13 +1006,15 @@ public class DateUtilTest { } @Test - public void test() { + public void isSameWeektest() { // 周六与周日比较 final boolean isSameWeek = DateUtil.isSameWeek(DateTime.of("2022-01-01", "yyyy-MM-dd"), DateTime.of("2022-01-02", "yyyy-MM-dd"), true); Assert.assertTrue(isSameWeek); // 周日与周一比较 final boolean isSameWeek1 = DateUtil.isSameWeek(DateTime.of("2022-01-02", "yyyy-MM-dd"), DateTime.of("2022-01-03", "yyyy-MM-dd"), false); Assert.assertTrue(isSameWeek1); - + // 跨月比较 + final boolean isSameWeek2 = DateUtil.isSameWeek(DateTime.of("2021-12-29", "yyyy-MM-dd"), DateTime.of("2022-01-01", "yyyy-MM-dd"), true); + Assert.assertTrue(isSameWeek2); } } From 3b6cca7435a4256e57406dc70ed7e31d63948223 Mon Sep 17 00:00:00 2001 From: naooohu Date: Fri, 21 Jan 2022 00:55:34 +0800 Subject: [PATCH 04/43] =?UTF-8?q?fix=20=E6=8A=8A=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E4=B8=BA=E8=AE=BE=E7=BD=AE=E4=B8=BA=E5=BD=93=E5=89=8D=E5=91=A8?= =?UTF-8?q?=E7=9A=84=E7=AC=AC=E4=B8=80=E5=A4=A9=E4=BB=A3=E7=A0=81=E5=9D=97?= =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E5=88=B0=20CalendarUtil=20=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/date/CalendarUtil.java | 16 +++++++++++++++- .../main/java/cn/hutool/core/date/DateUtil.java | 15 +-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index 4c6d3093c..be7e6a41d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -353,12 +353,26 @@ public class CalendarUtil { * * @param cal1 日期1 * @param cal2 日期2 + * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日 * @return 是否为同一周 */ - public static boolean isSameWeek(Calendar cal1, Calendar cal2) { + public static boolean isSameWeek(Calendar cal1, Calendar cal2, boolean isMon) { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } + // 把所传日期设置为其当前周的第一天 + // 比较设置后的两个日期是否是同一天:true 代表同一周 + if (isMon) { + cal1.setFirstDayOfWeek(Calendar.MONDAY); + cal1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + cal2.setFirstDayOfWeek(Calendar.MONDAY); + cal2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); + } else { + cal1.setFirstDayOfWeek(Calendar.SUNDAY); + cal1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + cal2.setFirstDayOfWeek(Calendar.SUNDAY); + cal2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); + } return isSameDay(cal1, cal2); } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index 066777c78..c887ef349 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -1598,20 +1598,7 @@ public class DateUtil extends CalendarUtil { if (date1 == null || date2 == null) { throw new IllegalArgumentException("The date must not be null"); } - Calendar calendar1 = calendar(date1); - Calendar calendar2 = calendar(date2); - if (isMon) { - calendar1.setFirstDayOfWeek(Calendar.MONDAY); - calendar1.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - calendar2.setFirstDayOfWeek(Calendar.MONDAY); - calendar2.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - } else { - calendar1.setFirstDayOfWeek(Calendar.SUNDAY); - calendar1.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - calendar2.setFirstDayOfWeek(Calendar.SUNDAY); - calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - } - return CalendarUtil.isSameWeek(calendar1, calendar2); + return CalendarUtil.isSameWeek(calendar(date1), calendar(date2), isMon); } /** From 06db212f24c8cae7520fb02fdff192e1581db9f9 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 25 Jan 2022 10:46:53 +0800 Subject: [PATCH 05/43] add test --- .../src/test/java/cn/hutool/core/text/NamingCaseTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/text/NamingCaseTest.java b/hutool-core/src/test/java/cn/hutool/core/text/NamingCaseTest.java index a8800578a..62545d934 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/NamingCaseTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/NamingCaseTest.java @@ -12,4 +12,10 @@ public class NamingCaseTest { .set("customerNickV2", "customer_nick_v2") .forEach((key, value) -> Assert.assertEquals(value, NamingCase.toUnderlineCase(key))); } + + @Test + public void toUnderLineCaseTest2(){ + final String wPRunOZTime = NamingCase.toUnderlineCase("wPRunOZTime"); + Assert.assertEquals("w_P_run_OZ_time", wPRunOZTime); + } } From 0e78438658ea25339b25a84d7f458bbb7affbab8 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 25 Jan 2022 10:56:51 +0800 Subject: [PATCH 06/43] add method --- CHANGELOG.md | 4 +++- .../java/cn/hutool/extra/emoji/EmojiUtil.java | 21 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 680a1ace4..e5d3b0aa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,12 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-01-21) +# 5.7.21 (2022-01-25) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 +* 【extra 】 EmojiUtil增加方法(pr#519@Gitee) + ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java index 1a55be8a5..05af52f8c 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java @@ -130,15 +130,30 @@ public class EmojiUtil { } /** - * 将字符串中的Unicode Emoji字符转换为HTML表现形式 + * 将字符串中的Unicode Emoji字符转换为HTML表现形式(Hex方式) *

- * 例如:👦🏿 转换为 👦 + * 例如:👦🏿 转换为 👦 * * @param str 包含Emoji Unicode字符的字符串 * @return 替换后的字符串 */ public static String toHtml(String str) { - return EmojiParser.parseToHtmlHexadecimal(str); + return toHtml(str, true); + } + + /** + * 将字符串中的Unicode Emoji字符转换为HTML表现形式,例如: + *

+	 * 如果为hex形式,👦🏿 转换为 👦
+	 * 否则,👦🏿 转换为 👦
+	 * 

+	 *
+	 * @param str 包含Emoji Unicode字符的字符串
+	 * @return 替换后的字符串
+	 */
+	public static String toHtml(String str, boolean isHex) {
+		return isHex ? EmojiParser.parseToHtmlHexadecimal(str) :
+				EmojiParser.parseToHtmlDecimal(str);
 	}
 
 	/**

From 763027a7864fb322ec948abe5027b81b3d4c08b1 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Tue, 25 Jan 2022 11:05:23 +0800
Subject: [PATCH 07/43] add method

---
 CHANGELOG.md                                               | 2 ++
 .../src/main/java/cn/hutool/core/date/CalendarUtil.java    | 1 +
 .../src/test/java/cn/hutool/core/date/DateUtilTest.java    | 2 +-
 .../src/main/java/cn/hutool/extra/emoji/EmojiUtil.java     | 7 ++++---
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5d3b0aa6..66545ca77 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,9 +7,11 @@
 ### 🐣新特性
 * 【extra  】     增加jetbrick模板支持
 * 【extra  】     EmojiUtil增加方法(pr#519@Gitee)
+* 【core   】     DateUtil 添加两个日期是否同一周方法(pr#516@Gitee)
 
 ### 🐞Bug修复
 * 【core   】     修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github)
+* 【extra  】     修复EmojiUtil.toHtmlHex()方法(pr#519@Gitee)
 
 -------------------------------------------------------------------------------------------------------------
 # 5.7.20 (2022-01-20)
diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
index be7e6a41d..20c4fedae 100644
--- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java
@@ -355,6 +355,7 @@ public class CalendarUtil {
 	 * @param cal2 日期2
 	 * @param isMon 是否为周一。国内第一天为星期一,国外第一天为星期日
 	 * @return 是否为同一周
+	 * @since 5.7.21
 	 */
 	public static boolean isSameWeek(Calendar cal1, Calendar cal2, boolean isMon) {
 		if (cal1 == null || cal2 == null) {
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
index 0aea526a6..4201009c1 100644
--- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
@@ -1006,7 +1006,7 @@ public class DateUtilTest {
 	}
 
 	@Test
-	public void isSameWeektest() {
+	public void isSameWeekTest() {
 		// 周六与周日比较
 		final boolean isSameWeek = DateUtil.isSameWeek(DateTime.of("2022-01-01", "yyyy-MM-dd"), DateTime.of("2022-01-02", "yyyy-MM-dd"), true);
 		Assert.assertTrue(isSameWeek);
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
index 05af52f8c..099d62778 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java
@@ -126,19 +126,19 @@ public class EmojiUtil {
 	 * @return 替换后的字符串
 	 */
 	public static String toHtmlHex(String str) {
-		return EmojiParser.parseToHtmlHexadecimal(str);
+		return toHtml(str, true);
 	}
 
 	/**
 	 * 将字符串中的Unicode Emoji字符转换为HTML表现形式(Hex方式)
 	 * 

- * 例如:👦🏿 转换为 👦 + * 例如:👦🏿 转换为 👦 * * @param str 包含Emoji Unicode字符的字符串 * @return 替换后的字符串 */ public static String toHtml(String str) { - return toHtml(str, true); + return toHtml(str, false); } /** @@ -150,6 +150,7 @@ public class EmojiUtil { * * @param str 包含Emoji Unicode字符的字符串 * @return 替换后的字符串 + * @since 5.7.21 */ public static String toHtml(String str, boolean isHex) { return isHex ? EmojiParser.parseToHtmlHexadecimal(str) : From 48e0e99bb62ec0f5abed49699c897f171def1d53 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 25 Jan 2022 11:12:41 +0800 Subject: [PATCH 08/43] add ConditionGroup --- CHANGELOG.md | 1 + .../src/main/java/cn/hutool/db/sql/ConditionGroup.java | 9 ++++++--- .../test/java/cn/hutool/db/sql/ConditionGroupTest.java | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66545ca77..e125d95c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * 【extra 】 增加jetbrick模板支持 * 【extra 】 EmojiUtil增加方法(pr#519@Gitee) * 【core 】 DateUtil 添加两个日期是否同一周方法(pr#516@Gitee) +* 【db 】 新增条件组,用于处理复杂的where条件(pr#514@Gitee) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java index 33467287a..7dedf5603 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java @@ -10,8 +10,9 @@ import java.util.List; * 用于构建复杂where条件 * * @author tjh + * @since 5.7.21 */ -public class ConditionGroup extends Condition{ +public class ConditionGroup extends Condition { /** * 条件列表 */ @@ -23,7 +24,7 @@ public class ConditionGroup extends Condition{ * @param conditions 条件列表 */ public void addConditions(Condition... conditions) { - if(null == this.conditions) { + if (null == this.conditions) { this.conditions = conditions; } else { this.conditions = ArrayUtil.addAll(this.conditions, conditions); @@ -38,7 +39,9 @@ public class ConditionGroup extends Condition{ */ @Override public String toString(List paramValues) { - if (ArrayUtil.isEmpty(conditions)) return StrUtil.EMPTY; + if (ArrayUtil.isEmpty(conditions)) { + return StrUtil.EMPTY; + } final StringBuilder conditionStrBuilder = StrUtil.builder(); conditionStrBuilder.append("("); diff --git a/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java index 3c48c2218..843e0420b 100644 --- a/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java +++ b/hutool-db/src/test/java/cn/hutool/db/sql/ConditionGroupTest.java @@ -1,5 +1,7 @@ package cn.hutool.db.sql; +import cn.hutool.core.collection.ListUtil; +import org.junit.Assert; import org.junit.Test; public class ConditionGroupTest { @@ -20,7 +22,7 @@ public class ConditionGroupTest { final ConditionBuilder conditionBuilder = ConditionBuilder.of(cg2, condition4); - System.out.println(conditionBuilder.build()); - System.out.println(conditionBuilder.getParamValues()); + Assert.assertEquals("((a = ? OR b = ?) AND c = ?) AND d = ?", conditionBuilder.build()); + Assert.assertEquals(ListUtil.of("A", "B", "C", "D"), conditionBuilder.getParamValues()); } } From bd89ec9335b4e2e3121548ad7a48e06914dbf5ca Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 26 Jan 2022 10:31:07 +0800 Subject: [PATCH 09/43] fix getUsed bug --- CHANGELOG.md | 3 +- .../java/cn/hutool/system/oshi/CpuInfo.java | 32 ++++++++++++------- .../test/java/cn/hutool/system/OshiTest.java | 10 ++++++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e125d95c1..22af4cfc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-01-25) +# 5.7.21 (2022-01-26) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 @@ -13,6 +13,7 @@ ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) * 【extra 】 修复EmojiUtil.toHtmlHex()方法(pr#519@Gitee) +* 【system 】 修复CpuInfo.getUsed()方法(issue#2116@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.20 (2022-01-20) diff --git a/hutool-system/src/main/java/cn/hutool/system/oshi/CpuInfo.java b/hutool-system/src/main/java/cn/hutool/system/oshi/CpuInfo.java index 531e06cc2..c9d3fdb47 100644 --- a/hutool-system/src/main/java/cn/hutool/system/oshi/CpuInfo.java +++ b/hutool-system/src/main/java/cn/hutool/system/oshi/CpuInfo.java @@ -1,5 +1,6 @@ package cn.hutool.system.oshi; +import cn.hutool.core.util.NumberUtil; import oshi.hardware.CentralProcessor; import java.text.DecimalFormat; @@ -31,7 +32,7 @@ public class CpuInfo { /** * CPU用户使用率 */ - private double used; + private double user; /** * CPU当前等待率 @@ -75,16 +76,16 @@ public class CpuInfo { * @param cpuNum CPU核心数 * @param toTal CPU总的使用率 * @param sys CPU系统使用率 - * @param used CPU用户使用率 + * @param user CPU用户使用率 * @param wait CPU当前等待率 * @param free CPU当前空闲率 * @param cpuModel CPU型号信息 */ - public CpuInfo(Integer cpuNum, double toTal, double sys, double used, double wait, double free, String cpuModel) { + public CpuInfo(Integer cpuNum, double toTal, double sys, double user, double wait, double free, String cpuModel) { this.cpuNum = cpuNum; this.toTal = toTal; this.sys = sys; - this.used = used; + this.user = user; this.wait = wait; this.free = free; this.cpuModel = cpuModel; @@ -114,12 +115,12 @@ public class CpuInfo { this.sys = sys; } - public double getUsed() { - return used; + public double getUser() { + return user; } - public void setUsed(double used) { - this.used = used; + public void setUser(double user) { + this.user = user; } public double getWait() { @@ -154,16 +155,25 @@ public class CpuInfo { this.ticks = ticks; } + /** + * 获取用户+系统的总的CPU使用率 + * + * @return 总CPU使用率 + */ + public double getUsed() { + return NumberUtil.sub(100, this.free); + } + @Override public String toString() { return "CpuInfo{" + "CPU核心数=" + cpuNum + ", CPU总的使用率=" + toTal + ", CPU系统使用率=" + sys + - ", CPU用户使用率=" + used + + ", CPU用户使用率=" + user + ", CPU当前等待率=" + wait + ", CPU当前空闲率=" + free + - ", CPU利用率=" + LOAD_FORMAT.format(100 - free) + + ", CPU利用率=" + getUsed() + ", CPU型号信息='" + cpuModel + '\'' + '}'; } @@ -185,7 +195,7 @@ public class CpuInfo { final long totalCpu = ticks.totalCpu(); this.toTal = totalCpu; this.sys = formatDouble(ticks.cSys, totalCpu); - this.used = formatDouble(ticks.user, totalCpu); + this.user = formatDouble(ticks.user, totalCpu); this.wait = formatDouble(ticks.ioWait, totalCpu); this.free = formatDouble(ticks.idle, totalCpu); } diff --git a/hutool-system/src/test/java/cn/hutool/system/OshiTest.java b/hutool-system/src/test/java/cn/hutool/system/OshiTest.java index 88abfdced..2bddf3b0b 100644 --- a/hutool-system/src/test/java/cn/hutool/system/OshiTest.java +++ b/hutool-system/src/test/java/cn/hutool/system/OshiTest.java @@ -1,8 +1,10 @@ package cn.hutool.system; +import cn.hutool.core.lang.Console; import cn.hutool.system.oshi.CpuInfo; import cn.hutool.system.oshi.OshiUtil; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import oshi.software.os.OSProcess; @@ -28,4 +30,12 @@ public class OshiTest { final OSProcess currentProcess = OshiUtil.getCurrentProcess(); Assert.assertEquals("java", currentProcess.getName()); } + + @Test + @Ignore + public void getUsedTest(){ + while (true){ + Console.log(OshiUtil.getCpuInfo().getUsed()); + } + } } From 201290d7c4275e8e61ed6aa3330f8b7e901776e3 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 26 Jan 2022 10:34:27 +0800 Subject: [PATCH 10/43] update dependency --- hutool-db/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index f314f3191..b49692e91 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -167,7 +167,7 @@ com.h2database h2 - 2.0.206 + 2.1.210 test From f729ba7b9cd984a0320c1a826ffb678401136d28 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 26 Jan 2022 17:11:42 +0800 Subject: [PATCH 11/43] add method --- CHANGELOG.md | 2 ++ .../hutool/core/date/LocalDateTimeUtil.java | 18 ++++++++++ .../main/java/cn/hutool/core/date/Month.java | 36 ++++++++++++++++--- .../core/date/LocalDateTimeUtilTest.java | 20 +++++++++++ .../java/cn/hutool/core/date/MonthTest.java | 11 ++++++ 5 files changed, 82 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 22af4cfc9..e53326887 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ * 【extra 】 EmojiUtil增加方法(pr#519@Gitee) * 【core 】 DateUtil 添加两个日期是否同一周方法(pr#516@Gitee) * 【db 】 新增条件组,用于处理复杂的where条件(pr#514@Gitee) +* 【core 】 新增LocalDateTimeUtil.weekOfYear(issue#I4RWXC@Gitee) +* 【core 】 Month增加toJdkMonth、getValueBaseOne ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java index 102fdff4e..b065c4ed1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java @@ -22,6 +22,7 @@ import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalUnit; +import java.time.temporal.WeekFields; import java.util.Date; import java.util.TimeZone; @@ -562,4 +563,21 @@ public class LocalDateTimeUtil { return startTime.isAfter(realEndTime) || endTime.isBefore(realStartTime); } + /** + * 获得指定日期是所在年份的第几周,如: + *
    + *
  • 如果一年的第一天是星期一,则第一周从第一天开始,没有零周
  • + *
  • 如果一年的第二天是星期一,则第一周从第二天开始,而第一天在零周
  • + *
  • 如果一年中的第4天是星期一,则第1周从第4周开始,第1至第3周在零周开始
  • + *
  • 如果一年中的第5天是星期一,则第二周从第5周开始,第1至第4周在第1周
  • + *
+ * + * + * @param date 日期({@link LocalDate} 或者 {@link LocalDateTime}等) + * @return 所在年的第几周 + * @since 5.7.21 + */ + public static int weekOfYear(TemporalAccessor date){ + return TemporalAccessorUtil.get(date, WeekFields.ISO.weekOfYear()); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/Month.java b/hutool-core/src/main/java/cn/hutool/core/date/Month.java index 0d82a6b5e..144898155 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/Month.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/Month.java @@ -1,5 +1,7 @@ package cn.hutool.core.date; +import cn.hutool.core.lang.Assert; + import java.util.Calendar; /** @@ -93,14 +95,27 @@ public enum Month { } /** - * 获取{@link Calendar}中的对应值 + * 获取{@link Calendar}中的对应值
+ * 此值从0开始,即0表示一月 * - * @return {@link Calendar}中的对应值 + * @return {@link Calendar}中的对应月份值,从0开始计数 */ public int getValue() { return this.value; } + /** + * 获取月份值,此值与{@link java.time.Month}对应
+ * 此值从1开始,即1表示一月 + * + * @return 月份值,对应{@link java.time.Month},从1开始计数 + * @since 5.7.21 + */ + public int getValueBaseOne() { + Assert.isFalse(this == UNDECIMBER, "Unsupported UNDECIMBER Field"); + return getValue() + 1; + } + /** * 获取此月份最后一天的值,不支持的月份(例如UNDECIMBER)返回-1 * @@ -165,17 +180,28 @@ public enum Month { /** * 获得指定月的最后一天 - * @param month 月份,从0开始 + * + * @param month 月份,从0开始 * @param isLeapYear 是否为闰年,闰年只对二月有影响 * @return 最后一天,可能为28,29,30,31 * @since 5.4.7 */ - public static int getLastDay(int month, boolean isLeapYear){ + public static int getLastDay(int month, boolean isLeapYear) { int lastDay = DAYS_OF_MONTH[month]; - if (isLeapYear && Calendar.FEBRUARY == month){ + if (isLeapYear && Calendar.FEBRUARY == month) { // 二月 lastDay += 1; } return lastDay; } + + /** + * 转换为{@link java.time.Month} + * + * @return {@link java.time.Month} + * @since 5.7.21 + */ + public java.time.Month toJdkMonth() { + return java.time.Month.of(getValueBaseOne()); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java index 8f35c59a5..dd1ec960a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java @@ -197,4 +197,24 @@ public class LocalDateTimeUtilTest { Assert.assertTrue(LocalDateTimeUtil.isOverlap(oneStartTime2,oneEndTime2,realStartTime,realEndTime)); Assert.assertFalse(LocalDateTimeUtil.isOverlap(oneStartTime3,oneEndTime3,realStartTime,realEndTime)); } + + @Test + public void weekOfYearTest(){ + LocalDate date1 = LocalDate.of(2021, 12, 31); + final int weekOfYear1 = LocalDateTimeUtil.weekOfYear(date1); + Assert.assertEquals(weekOfYear1, 52); + + final int weekOfYear2 = LocalDateTimeUtil.weekOfYear(date1.atStartOfDay()); + Assert.assertEquals(weekOfYear2, 52); + } + + @Test + public void weekOfYearTest2(){ + LocalDate date1 = LocalDate.of(2022, 1, 31); + final int weekOfYear1 = LocalDateTimeUtil.weekOfYear(date1); + Assert.assertEquals(weekOfYear1, 52); + + final int weekOfYear2 = LocalDateTimeUtil.weekOfYear(date1.atStartOfDay()); + Assert.assertEquals(weekOfYear2, 52); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java b/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java index dce94bb09..7a7929f39 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/MonthTest.java @@ -37,4 +37,15 @@ public class MonthTest { lastDay = Month.of(Calendar.DECEMBER).getLastDay(true); Assert.assertEquals(31, lastDay); } + + @Test + public void toJdkMonthTest(){ + final java.time.Month month = Month.AUGUST.toJdkMonth(); + Assert.assertEquals(java.time.Month.AUGUST, month); + } + + @Test(expected = IllegalArgumentException.class) + public void toJdkMonthTest2(){ + Month.UNDECIMBER.toJdkMonth(); + } } From 54a6ba09c66d680b027c66c6219bdd06df02ed75 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 26 Jan 2022 18:35:16 +0800 Subject: [PATCH 12/43] fix cv --- CHANGELOG.md | 1 + .../cn/hutool/core/text/csv/CsvWriter.java | 29 ++++++++++++------- .../hutool/core/text/csv/CsvWriterTest.java | 3 +- .../hutool/extra/qrcode/QrCodeUtilTest.java | 2 ++ 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e53326887..470e96df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * 【db 】 新增条件组,用于处理复杂的where条件(pr#514@Gitee) * 【core 】 新增LocalDateTimeUtil.weekOfYear(issue#I4RWXC@Gitee) * 【core 】 Month增加toJdkMonth、getValueBaseOne +* 【core 】 CsvWriter修改规则,去除末尾多余换行符(issue#I4RSQY@Gitee) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java index 878011082..5c386214e 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/csv/CsvWriter.java @@ -1,6 +1,7 @@ package cn.hutool.core.text.csv; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.ArrayIter; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.FileUtil; @@ -45,6 +46,10 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { * 是否处于新行开始 */ private boolean newline = true; + /** + * 是否首行,即CSV开始的位置,当初始化时默认为true,一旦写入内容,为false + */ + private boolean isFirstLine = true; // --------------------------------------------------------------------------------------------------- Constructor start @@ -183,13 +188,7 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { * @throws IORuntimeException IO异常 */ public CsvWriter write(String[]... lines) throws IORuntimeException { - if (ArrayUtil.isNotEmpty(lines)) { - for (final String[] values : lines) { - appendLine(values); - } - flush(); - } - return this; + return write(new ArrayIter<>(lines)); } /** @@ -320,9 +319,14 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { public CsvWriter writeComment(String comment) { Assert.notNull(this.config.commentCharacter, "Comment is disable!"); try { + if(isFirstLine){ + // 首行不补换行符 + isFirstLine = false; + }else { + writer.write(config.lineDelimiter); + } writer.write(this.config.commentCharacter); writer.write(comment); - writer.write(config.lineDelimiter); newline = true; } catch (IOException e) { throw new IORuntimeException(e); @@ -366,12 +370,17 @@ public final class CsvWriter implements Closeable, Flushable, Serializable { * @param fields 字段列表 ({@code null} 值会被做为空值追加) * @throws IOException IO异常 */ - private void doAppendLine(final String... fields) throws IOException { + private void doAppendLine(String... fields) throws IOException { if (null != fields) { + if(isFirstLine){ + // 首行不补换行符 + isFirstLine = false; + }else { + writer.write(config.lineDelimiter); + } for (String field : fields) { appendField(field); } - writer.write(config.lineDelimiter); newline = true; } } diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java index 18203196c..0564af9ac 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java @@ -2,7 +2,6 @@ package cn.hutool.core.text.csv; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; -import org.junit.Ignore; import org.junit.Test; public class CsvWriterTest { @@ -19,6 +18,8 @@ public class CsvWriterTest { CharsetUtil.CHARSET_GBK, false, csvWriteConfig); writer.writeHeaderLine("name", "gender", "address"); + writer.writeLine("张三", "男", "XX市XX区"); + writer.writeLine("李四", "男", "XX市XX区,01号"); writer.close(); } } diff --git a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java index 7f31d796f..30dde68d6 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java @@ -94,4 +94,6 @@ public class QrCodeUtilTest { final BufferedImage image = QrCodeUtil.generate("content111", BarcodeFormat.PDF_417, QrConfig.create()); Assert.assertNotNull(image); } + + } From 344212f5b6fe00e826ed1c2a2d29c7f188eab08d Mon Sep 17 00:00:00 2001 From: youzipi Date: Wed, 26 Jan 2022 18:36:15 +0800 Subject: [PATCH 13/43] feat(core:DateUtil): add `rangeFunc` and `rangeConsume` --- .../java/cn/hutool/core/date/DateUtil.java | 58 ++++++++++++++++--- .../java/cn/hutool/core/lang/RangeTest.java | 26 +++++++++ 2 files changed, 77 insertions(+), 7 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index c887ef349..268083716 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -20,14 +20,10 @@ import java.time.LocalDateTime; import java.time.Year; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; -import java.util.TimeZone; +import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; /** * 时间工具类 @@ -1885,6 +1881,54 @@ public class DateUtil extends CalendarUtil { return new DateRange(start, end, unit); } + /** + * 按日期范围遍历,执行 function + * + * @param start 起始日期时间(包括) + * @param end 结束日期时间 + * @param unit 步进单位 + * @param func 每次遍历要执行的 function + * @param + * @return + */ + public static List rangeFunc(Date start, Date end, final DateField unit, Function func) { + if (start == null || end == null || start.after(end)) { + return Collections.emptyList(); + } else { + ArrayList list = new ArrayList<>(); + DateRange dateRange = range(start, end, unit); + while (dateRange.hasNext()) { + DateTime next = dateRange.next(); + Date date = next.toJdkDate(); + T result = func.apply(date); + list.add(result); + } + return list; + } + } + + /** + * 按日期范围遍历,执行 consumer + * + * @param start 起始日期时间(包括) + * @param end 结束日期时间 + * @param unit 步进单位 + * @param consumer 每次遍历要执行的 consumer + * @return + */ + public static void rangeConsume(Date start, Date end, final DateField unit, Consumer consumer) { + if (start == null || end == null || start.after(end)) { + return; + } else { + DateRange dateRange = range(start, end, unit); + while (dateRange.hasNext()) { + DateTime next = dateRange.next(); + Date date = next.toJdkDate(); + consumer.accept(date); + } + } + } + /** * 创建日期范围生成器 * diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java index c08e5dbb1..9feb53927 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/RangeTest.java @@ -36,6 +36,32 @@ public class RangeTest { Assert.assertFalse(range.hasNext()); } + @Test + public void dateRangeFuncTest() { + DateTime start = DateUtil.parse("2021-01-01"); + DateTime end = DateUtil.parse("2021-01-03"); + + List dayOfMonthList = DateUtil.rangeFunc(start, end, DateField.DAY_OF_YEAR, a -> DateTime.of(a).dayOfMonth()); + Assert.assertArrayEquals(dayOfMonthList.toArray(new Integer[]{}), new Integer[]{1, 2, 3}); + + List dayOfMonthList2 = DateUtil.rangeFunc(null, null, DateField.DAY_OF_YEAR, a -> DateTime.of(a).dayOfMonth()); + Assert.assertArrayEquals(dayOfMonthList2.toArray(new Integer[]{}), new Integer[]{}); + } + + @Test + public void dateRangeConsumeTest() { + DateTime start = DateUtil.parse("2021-01-01"); + DateTime end = DateUtil.parse("2021-01-03"); + + StringBuilder sb = new StringBuilder(); + DateUtil.rangeConsume(start, end, DateField.DAY_OF_YEAR, a -> sb.append(DateTime.of(a).dayOfMonth()).append("#")); + Assert.assertEquals(sb.toString(), "1#2#3#"); + + StringBuilder sb2 = new StringBuilder(); + DateUtil.rangeConsume(null, null, DateField.DAY_OF_YEAR, a -> sb.append(DateTime.of(a).dayOfMonth()).append("#")); + Assert.assertEquals(sb2.toString(), ""); + } + @Test public void dateRangeTest2() { DateTime start = DateUtil.parse("2021-01-31"); From f7ab6b0ccf87c2a0e0e32ffebeec2cf27bab72e9 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 09:04:23 +0800 Subject: [PATCH 14/43] add methods --- CHANGELOG.md | 4 +- .../java/cn/hutool/core/date/DateTime.java | 30 +++++++++++-- .../java/cn/hutool/core/date/DateUtil.java | 42 +++++++++---------- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 470e96df7..5bb8d6deb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-01-26) +# 5.7.21 (2022-01-27) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 @@ -12,6 +12,8 @@ * 【core 】 新增LocalDateTimeUtil.weekOfYear(issue#I4RWXC@Gitee) * 【core 】 Month增加toJdkMonth、getValueBaseOne * 【core 】 CsvWriter修改规则,去除末尾多余换行符(issue#I4RSQY@Gitee) +* 【core 】 DateUtil增加rangeFunc和rangeConsume(issue#I4RSQY@Gitee) +* 【core 】 DateTime增加setUseJdkToStringStyle方法 ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java b/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java index 76547adfc..2956eade4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateTime.java @@ -24,13 +24,30 @@ import java.util.Locale; import java.util.TimeZone; /** - * 包装java.util.Date + * 包装{@link Date}
+ * 此类继承了{@link Date},并提供扩展方法,如时区等。
+ * 此类重写了父类的{@code toString()}方法,返回值为"yyyy-MM-dd HH:mm:ss"格式 * * @author xiaoleilu */ public class DateTime extends Date { private static final long serialVersionUID = -5395712593979185936L; + private static boolean useJdkToStringStyle = false; + + /** + * 设置全局的,是否使用{@link Date}默认的toString()格式
+ * 如果为{@code true},则调用toString()时返回"EEE MMM dd HH:mm:ss zzz yyyy"格式,
+ * 如果为{@code false},则返回"yyyy-MM-dd HH:mm:ss",
+ * 默认为{@code false} + * + * @param customUseJdkToStringStyle 是否使用{@link Date}默认的toString()格式 + * @since 5.7.21 + */ + public static void setUseJdkToStringStyle(boolean customUseJdkToStringStyle){ + useJdkToStringStyle = customUseJdkToStringStyle; + } + /** * 是否可变对象 */ @@ -932,13 +949,18 @@ public class DateTime extends Date { // -------------------------------------------------------------------- toString start /** - * 转为"yyyy-MM-dd HH:mm:ss" 格式字符串
- * 如果时区被设置,会转换为其时区对应的时间,否则转换为当前地点对应的时区 + * 转为字符串,如果时区被设置,会转换为其时区对应的时间,否则转换为当前地点对应的时区
+ * 可以调用{@link DateTime#setUseJdkToStringStyle(boolean)} 方法自定义默认的风格
+ * 如果{@link #useJdkToStringStyle}为{@code true},返回"EEE MMM dd HH:mm:ss zzz yyyy"格式,
+ * 如果为{@code false},则返回"yyyy-MM-dd HH:mm:ss" * - * @return "yyyy-MM-dd HH:mm:ss" 格式字符串 + * @return 格式字符串 */ @Override public String toString() { + if(useJdkToStringStyle){ + return super.toString(); + } return toString(this.timeZone); } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java index 268083716..164855a09 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java @@ -20,7 +20,15 @@ import java.time.LocalDateTime; import java.time.Year; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; -import java.util.*; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Locale; +import java.util.TimeZone; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; @@ -1888,23 +1896,19 @@ public class DateUtil extends CalendarUtil { * @param end 结束日期时间 * @param unit 步进单位 * @param func 每次遍历要执行的 function - * @param - * @return + * @param Date经过函数处理结果类型 + * @return 结果列表 + * @since 5.7.21 */ public static List rangeFunc(Date start, Date end, final DateField unit, Function func) { if (start == null || end == null || start.after(end)) { return Collections.emptyList(); - } else { - ArrayList list = new ArrayList<>(); - DateRange dateRange = range(start, end, unit); - while (dateRange.hasNext()) { - DateTime next = dateRange.next(); - Date date = next.toJdkDate(); - T result = func.apply(date); - list.add(result); - } - return list; } + ArrayList list = new ArrayList<>(); + for(DateTime date : range(start, end, unit)){ + list.add(func.apply(date)); + } + return list; } /** @@ -1914,19 +1918,13 @@ public class DateUtil extends CalendarUtil { * @param end 结束日期时间 * @param unit 步进单位 * @param consumer 每次遍历要执行的 consumer - * @return + * @since 5.7.21 */ public static void rangeConsume(Date start, Date end, final DateField unit, Consumer consumer) { if (start == null || end == null || start.after(end)) { return; - } else { - DateRange dateRange = range(start, end, unit); - while (dateRange.hasNext()) { - DateTime next = dateRange.next(); - Date date = next.toJdkDate(); - consumer.accept(date); - } } + range(start, end, unit).forEach(consumer); } /** @@ -1937,7 +1935,7 @@ public class DateUtil extends CalendarUtil { * @param unit 步进单位 * @return {@link DateRange} */ - public static List rangeToList(Date start, Date end, final DateField unit) { + public static List rangeToList(Date start, Date end, DateField unit) { return CollUtil.newArrayList((Iterable) range(start, end, unit)); } From f267e9e6b5b60a0bfb5f533925242a5504e21a63 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 09:22:12 +0800 Subject: [PATCH 15/43] add methods --- .../java/cn/hutool/core/bean/BeanDescCache.java | 16 +++++++++++++--- .../java/cn/hutool/core/bean/BeanInfoCache.java | 10 ++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java index d1eaa920a..b41d030c2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDescCache.java @@ -6,8 +6,8 @@ import cn.hutool.core.lang.func.Func0; /** * Bean属性缓存
* 缓存用于防止多次反射造成的性能问题 - * @author Looly * + * @author Looly */ public enum BeanDescCache { INSTANCE; @@ -16,12 +16,22 @@ public enum BeanDescCache { /** * 获得属性名和{@link BeanDesc}Map映射 + * * @param beanClass Bean的类 - * @param supplier 对象不存在时创建对象的函数 + * @param supplier 对象不存在时创建对象的函数 * @return 属性名和{@link BeanDesc}映射 * @since 5.4.2 */ - public BeanDesc getBeanDesc(Class beanClass, Func0 supplier){ + public BeanDesc getBeanDesc(Class beanClass, Func0 supplier) { return bdCache.get(beanClass, supplier); } + + /** + * 清空全局的Bean属性缓存 + * + * @since 5.7.21 + */ + public void clear() { + this.bdCache.clear(); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanInfoCache.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanInfoCache.java index af9b83a54..7a950ba0c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanInfoCache.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanInfoCache.java @@ -56,6 +56,16 @@ public enum BeanInfoCache { getCache(ignoreCase).put(beanClass, fieldNamePropertyDescriptorMap); } + /** + * 清空缓存 + * + * @since 5.7.21 + */ + public void clear() { + this.pdCache.clear(); + this.ignoreCasePdCache.clear(); + } + /** * 根据是否忽略字段名的大小写,返回不用Cache对象 * From 7615d30f8bf046140a48238bcf5f1f582431d542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Thu, 27 Jan 2022 10:46:31 +0800 Subject: [PATCH 16/43] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=EF=BC=9AListUtilTest.pageTest=20=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=90=8E=EF=BC=8C=E5=9B=A0PageUtil.firstPageNo?= =?UTF-8?q?=E5=80=BC=E5=8F=98=E6=88=902=E5=AF=BC=E8=87=B4=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hutool/core/collection/ListUtilTest.java | 19 +++++++++++-------- .../cn/hutool/core/util/PageUtilTest.java | 17 ++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java index 912df5904..5cecd5de3 100644 --- a/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/collection/ListUtilTest.java @@ -19,7 +19,7 @@ import java.util.Map; public class ListUtilTest { @Test - public void splitTest(){ + public void splitTest() { List> lists = ListUtil.split(null, 3); Assert.assertEquals(ListUtil.empty(), lists); @@ -60,7 +60,7 @@ public class ListUtilTest { } @Test - public void splitAvgTest(){ + public void splitAvgTest() { List> lists = ListUtil.splitAvg(null, 3); Assert.assertEquals(ListUtil.empty(), lists); @@ -80,13 +80,13 @@ public class ListUtilTest { } @Test(expected = IllegalArgumentException.class) - public void splitAvgNotZero(){ + public void splitAvgNotZero() { // limit不能小于等于0 ListUtil.splitAvg(Arrays.asList(1, 2, 3, 4), 0); } @Test - public void editTest(){ + public void editTest() { List a = ListUtil.toLinkedList("1", "2", "3"); final List filter = (List) CollUtil.edit(a, str -> "edit" + str); Assert.assertEquals("edit1", filter.get(0)); @@ -104,7 +104,7 @@ public class ListUtilTest { } @Test - public void pageTest(){ + public void pageTest() { List a = ListUtil.toLinkedList(1, 2, 3,4,5); PageUtil.setFirstPageNo(1); @@ -167,10 +167,13 @@ public class ListUtilTest { Assert.assertArrayEquals(new int[]{}, pageListData.get(0).stream().mapToInt(Integer::valueOf).toArray()); Assert.assertArrayEquals(new int[]{3, 4}, pageListData.get(1).stream().mapToInt(Integer::valueOf).toArray()); Assert.assertArrayEquals(new int[]{5}, pageListData.get(2).stream().mapToInt(Integer::valueOf).toArray()); + + // 恢复默认值,避免影响其他测试用例 + PageUtil.setFirstPageNo(0); } @Test - public void subTest(){ + public void subTest() { final List of = ListUtil.of(1, 2, 3, 4); final List sub = ListUtil.sub(of, 2, 4); sub.remove(0); @@ -181,10 +184,10 @@ public class ListUtilTest { } @Test - public void sortByPropertyTest(){ + public void sortByPropertyTest() { @Data @AllArgsConstructor - class TestBean{ + class TestBean { private int order; private String name; } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java index 46e6e606b..f382b8711 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/PageUtilTest.java @@ -5,32 +5,31 @@ import org.junit.Test; /** * 分页单元测试 - * @author Looly * + * @author Looly */ public class PageUtilTest { - + @Test - public void transToStartEndTest(){ - PageUtil.setFirstPageNo(0); + public void transToStartEndTest() { int[] startEnd1 = PageUtil.transToStartEnd(0, 10); Assert.assertEquals(0, startEnd1[0]); Assert.assertEquals(10, startEnd1[1]); - + int[] startEnd2 = PageUtil.transToStartEnd(1, 10); Assert.assertEquals(10, startEnd2[0]); Assert.assertEquals(20, startEnd2[1]); } - + @Test - public void totalPage(){ + public void totalPage() { int totalPage = PageUtil.totalPage(20, 3); Assert.assertEquals(7, totalPage); } - + @Test public void rainbowTest() { int[] rainbow = PageUtil.rainbow(5, 20, 6); - Assert.assertArrayEquals(new int[] {3, 4, 5, 6, 7, 8}, rainbow); + Assert.assertArrayEquals(new int[]{3, 4, 5, 6, 7, 8}, rainbow); } } From e2d71ee5609c863bf2ad082c7bd72826f2a4684a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Thu, 27 Jan 2022 10:58:09 +0800 Subject: [PATCH 17/43] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java | 4 ++-- .../src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java index dd1ec960a..674ff8a9b 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java @@ -212,9 +212,9 @@ public class LocalDateTimeUtilTest { public void weekOfYearTest2(){ LocalDate date1 = LocalDate.of(2022, 1, 31); final int weekOfYear1 = LocalDateTimeUtil.weekOfYear(date1); - Assert.assertEquals(weekOfYear1, 52); + Assert.assertEquals(weekOfYear1, 5); final int weekOfYear2 = LocalDateTimeUtil.weekOfYear(date1.atStartOfDay()); - Assert.assertEquals(weekOfYear2, 52); + Assert.assertEquals(weekOfYear2, 5); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java index 0564af9ac..e79c9b784 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.text.csv; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import org.junit.Ignore; import org.junit.Test; public class CsvWriterTest { From 9b5b72b1e39b0fb7e34dd75c36a861cfe0be4c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E8=89=AF?= <841369634@qq.com> Date: Thu, 27 Jan 2022 11:01:54 +0800 Subject: [PATCH 18/43] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E4=B8=AD=EF=BC=8C=E9=A2=84=E6=9C=9F=E5=80=BC=E5=92=8C=E5=AE=9E?= =?UTF-8?q?=E9=99=85=E5=80=BC=E5=8F=82=E6=95=B0=E5=8F=8D=E4=BA=86=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/date/LocalDateTimeUtilTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java index 674ff8a9b..57d6eb717 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/LocalDateTimeUtilTest.java @@ -202,19 +202,19 @@ public class LocalDateTimeUtilTest { public void weekOfYearTest(){ LocalDate date1 = LocalDate.of(2021, 12, 31); final int weekOfYear1 = LocalDateTimeUtil.weekOfYear(date1); - Assert.assertEquals(weekOfYear1, 52); + Assert.assertEquals(52, weekOfYear1); final int weekOfYear2 = LocalDateTimeUtil.weekOfYear(date1.atStartOfDay()); - Assert.assertEquals(weekOfYear2, 52); + Assert.assertEquals(52, weekOfYear2); } @Test public void weekOfYearTest2(){ LocalDate date1 = LocalDate.of(2022, 1, 31); final int weekOfYear1 = LocalDateTimeUtil.weekOfYear(date1); - Assert.assertEquals(weekOfYear1, 5); + Assert.assertEquals(5, weekOfYear1); final int weekOfYear2 = LocalDateTimeUtil.weekOfYear(date1.atStartOfDay()); - Assert.assertEquals(weekOfYear2, 5); + Assert.assertEquals(5, weekOfYear2); } } From 10735f11bd1e1430b787d45fb3561824de89dcef Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 27 Jan 2022 12:39:40 +0800 Subject: [PATCH 19/43] remove redundant text in package-info.java of module hutool-log --- hutool-log/src/main/java/cn/hutool/log/package-info.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hutool-log/src/main/java/cn/hutool/log/package-info.java b/hutool-log/src/main/java/cn/hutool/log/package-info.java index 1434801bb..974f4a437 100644 --- a/hutool-log/src/main/java/cn/hutool/log/package-info.java +++ b/hutool-log/src/main/java/cn/hutool/log/package-info.java @@ -1,8 +1,8 @@ /** * Hutool-log只是一个日志的通用门面,功能类似于Slf4j。
- * 根据加入ClassPath中的jar包动态检测日志实现的方式,使日志使用个更加便利灵活。 - * + * 根据加入ClassPath中的jar包动态检测日志实现的方式,使日志使用更加便利灵活。 + * * @author looly * */ -package cn.hutool.log; \ No newline at end of file +package cn.hutool.log; From eb89096bd1d5cd65b829471c028c3224e2af03d4 Mon Sep 17 00:00:00 2001 From: sam Date: Thu, 27 Jan 2022 13:01:11 +0800 Subject: [PATCH 20/43] miss importing 'org.junit.Ignore' --- .../src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java index 0564af9ac..e79c9b784 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.text.csv; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import org.junit.Ignore; import org.junit.Test; public class CsvWriterTest { From e02d599964bf2485831c87b4cf914c8a3ea9d6c8 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 20:09:45 +0800 Subject: [PATCH 21/43] fix comment --- .../cn/hutool/core/date/CalendarUtil.java | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java index 20c4fedae..91744046f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java @@ -132,7 +132,7 @@ public class CalendarUtil { } /** - * 获取秒级别的开始时间,即忽略毫秒部分 + * 修改秒级别的开始时间,即忽略毫秒部分 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -143,7 +143,7 @@ public class CalendarUtil { } /** - * 获取秒级别的结束时间,即毫秒设置为999 + * 修改秒级别的结束时间,即毫秒设置为999 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -154,7 +154,7 @@ public class CalendarUtil { } /** - * 获取某小时的开始时间 + * 修改某小时的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -164,7 +164,7 @@ public class CalendarUtil { } /** - * 获取某小时的结束时间 + * 修改某小时的结束时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -174,7 +174,7 @@ public class CalendarUtil { } /** - * 获取某分钟的开始时间 + * 修改某分钟的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -184,7 +184,7 @@ public class CalendarUtil { } /** - * 获取某分钟的结束时间 + * 修改某分钟的结束时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -194,7 +194,7 @@ public class CalendarUtil { } /** - * 获取某天的开始时间 + * 修改某天的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -204,7 +204,7 @@ public class CalendarUtil { } /** - * 获取某天的结束时间 + * 修改某天的结束时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -214,7 +214,7 @@ public class CalendarUtil { } /** - * 获取给定日期当前周的开始时间,周一定为一周的开始时间 + * 修改给定日期当前周的开始时间,周一定为一周的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -224,7 +224,7 @@ public class CalendarUtil { } /** - * 获取给定日期当前周的开始时间 + * 修改给定日期当前周的开始时间 * * @param calendar 日期 {@link Calendar} * @param isMondayAsFirstDay 是否周一做为一周的第一天(false表示周日做为第一天) @@ -238,7 +238,7 @@ public class CalendarUtil { } /** - * 获取某周的结束时间,周日定为一周的结束 + * 修改某周的结束时间,周日定为一周的结束 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -248,7 +248,7 @@ public class CalendarUtil { } /** - * 获取某周的结束时间 + * 修改某周的结束时间 * * @param calendar 日期 {@link Calendar} * @param isSundayAsLastDay 是否周日做为一周的最后一天(false表示周六做为最后一天) @@ -261,7 +261,7 @@ public class CalendarUtil { } /** - * 获取某月的开始时间 + * 修改某月的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -271,7 +271,7 @@ public class CalendarUtil { } /** - * 获取某月的结束时间 + * 修改某月的结束时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -281,7 +281,7 @@ public class CalendarUtil { } /** - * 获取某季度的开始时间 + * 修改某季度的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -313,7 +313,7 @@ public class CalendarUtil { } /** - * 获取某年的开始时间 + * 修改某年的开始时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -323,7 +323,7 @@ public class CalendarUtil { } /** - * 获取某年的结束时间 + * 修改某年的结束时间 * * @param calendar 日期 {@link Calendar} * @return {@link Calendar} @@ -361,6 +361,11 @@ public class CalendarUtil { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } + + // 防止比较前修改原始Calendar对象 + cal1 = (Calendar) cal1.clone(); + cal2 = (Calendar) cal2.clone(); + // 把所传日期设置为其当前周的第一天 // 比较设置后的两个日期是否是同一天:true 代表同一周 if (isMon) { From cafc9d985d283aba4052f6643870966d15124507 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 20:35:02 +0800 Subject: [PATCH 22/43] add method --- CHANGELOG.md | 1 + .../cn/hutool/core/text/CharSequenceUtil.java | 40 +++++++++++++++++++ .../core/text/CharSequenceUtilTest.java | 7 ++++ .../hutool/core/text/csv/CsvWriterTest.java | 1 + 4 files changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bb8d6deb..46b525879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * 【core 】 CsvWriter修改规则,去除末尾多余换行符(issue#I4RSQY@Gitee) * 【core 】 DateUtil增加rangeFunc和rangeConsume(issue#I4RSQY@Gitee) * 【core 】 DateTime增加setUseJdkToStringStyle方法 +* 【core 】 CharSequenceUtil增加replace重载(issue#2122@Github) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index 2d7bcad89..4a308c14d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -3601,6 +3601,46 @@ public class CharSequenceUtil { return stringBuilder.toString(); } + /** + * 替换指定字符串的指定区间内字符为指定字符串,字符串只重复一次
+ * 此方法使用{@link String#codePoints()}完成拆分替换 + * + * @param str 字符串 + * @param startInclude 开始位置(包含) + * @param endExclude 结束位置(不包含) + * @param replacedStr 被替换的字符串 + * @return 替换后的字符串 + * @since 3.2.1 + */ + public static String replace(CharSequence str, int startInclude, int endExclude, CharSequence replacedStr) { + if (isEmpty(str)) { + return str(str); + } + final String originalStr = str(str); + int[] strCodePoints = originalStr.codePoints().toArray(); + final int strLength = strCodePoints.length; + if (startInclude > strLength) { + return originalStr; + } + if (endExclude > strLength) { + endExclude = strLength; + } + if (startInclude > endExclude) { + // 如果起始位置大于结束位置,不替换 + return originalStr; + } + + final StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < startInclude; i++) { + stringBuilder.append(new String(strCodePoints, i, 1)); + } + stringBuilder.append(replacedStr); + for (int i = endExclude; i < strLength; i++) { + stringBuilder.append(new String(strCodePoints, i, 1)); + } + return stringBuilder.toString(); + } + /** * 替换所有正则匹配的文本,并使用自定义函数决定如何替换
* replaceFun可以通过{@link Matcher}提取出匹配到的内容的不同部分,然后经过重新处理、组装变成新的内容放回原位。 diff --git a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java index 18b84edb2..07afd2b4a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/CharSequenceUtilTest.java @@ -22,6 +22,13 @@ public class CharSequenceUtilTest { Assert.assertEquals(replace, result); } + @Test + public void replaceByStrTest(){ + String replace = "SSM15930297701BeryAllen"; + String result = CharSequenceUtil.replace(replace, 5, 12, "***"); + Assert.assertEquals("SSM15***01BeryAllen", result); + } + @Test public void addPrefixIfNotTest(){ String str = "hutool"; diff --git a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java index 0564af9ac..e79c9b784 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/csv/CsvWriterTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.text.csv; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.CharsetUtil; +import org.junit.Ignore; import org.junit.Test; public class CsvWriterTest { From c9138ea12253b372674c8862260b035f2f13c794 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 20:43:38 +0800 Subject: [PATCH 23/43] fix comment --- .../src/main/java/cn/hutool/extra/emoji/EmojiUtil.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java index 099d62778..585eb8dad 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/emoji/EmojiUtil.java @@ -146,9 +146,10 @@ public class EmojiUtil { *
 	 * 如果为hex形式,👦🏿 转换为 &#x1f466;
 	 * 否则,👦🏿 转换为 &#128102;
-	 * 

+	 * 
* - * @param str 包含Emoji Unicode字符的字符串 + * @param str 包含Emoji Unicode字符的字符串 + * @param isHex 是否hex形式 * @return 替换后的字符串 * @since 5.7.21 */ From b4e3fe485a360606b8a1d8b54521a68305b8a1c1 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 27 Jan 2022 20:48:26 +0800 Subject: [PATCH 24/43] fix comment --- hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java index 7dedf5603..fb33305cd 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/ConditionGroup.java @@ -6,7 +6,7 @@ import cn.hutool.core.util.StrUtil; import java.util.List; /** - * 条件组
+ * 条件组
* 用于构建复杂where条件 * * @author tjh From 9d5c2ffc1a9037efe0a9e46f06feff0554ed87e6 Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Sat, 29 Jan 2022 17:34:52 +0800 Subject: [PATCH 25/43] =?UTF-8?q?=E6=96=B0=E5=A2=9EGenericBuilder?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hutool/core/builder/GenericBuilder.java | 252 ++++++++++++++++++ .../core/builder/GenericBuilderTest.java | 47 ++++ 2 files changed, 299 insertions(+) create mode 100644 hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java new file mode 100644 index 000000000..b8da21486 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -0,0 +1,252 @@ +package cn.hutool.core.builder; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + *

通用Builder

+ * 参考: 一看就会的java8通用Builder + *

使用方法如下:

+ *
+ * Box box = GenericBuilder
+ * 		      .of(Box::new)
+ * 		      .with(Box::setId, 1024L)
+ * 		      .with(Box::setTitle, "Hello World!")
+ * 		      .with(Box::setLength, 9)
+ * 		      .with(Box::setWidth, 8)
+ * 		      .with(Box::setHeight, 7)
+ * 		      .build();
+ *
+ * 
+ * + *

我们也可以对已创建的对象进行修改:

+ *
+ * Box boxModified = GenericBuilder
+ * 		      .of(() -> box)
+ * 		      .with(Box::setTitle, "Hello Friend!")
+ * 		      .with(Box::setLength, 3)
+ * 		      .with(Box::setWidth, 4)
+ * 		      .with(Box::setHeight, 5)
+ * 		      .build();
+ * 
+ * + * @author TomXin + * @since jdk1.8 + */ +public class GenericBuilder implements Builder { + + /** + * 实例化器 + */ + private final Supplier instantiator; + + /** + * 修改器集合 + */ + private final List> modifiers = new ArrayList<>(); + + /** + * 构造 + * + * @param instant 实例化器 + */ + public GenericBuilder(Supplier instant) { + this.instantiator = instant; + } + + /** + * 通过实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param 目标类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier instant) { + return new GenericBuilder<>(instant); + } + + /** + * 调用1参数方法 + * + * @param consumer 1参数Consumer + * @param p1 参数一 + * @param 参数一类型 + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer1 consumer, P1 p1) { + Consumer c = instance -> consumer.accept(instance, p1); + modifiers.add(c); + return this; + } + + /** + * 调用2参数方法 + * + * @param consumer 2参数Consumer + * @param p1 参数一 + * @param p2 参数二 + * @param 参数一类型 + * @param 参数二类型 + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer2 consumer, P1 p1, P2 p2) { + Consumer c = instance -> consumer.accept(instance, p1, p2); + modifiers.add(c); + return this; + } + + /** + * 调用3参数方法 + * + * @param consumer 3参数Consumer + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer3 consumer, P1 p1, P2 p2, P3 p3) { + Consumer c = instance -> consumer.accept(instance, p1, p2, p3); + modifiers.add(c); + return this; + } + + /** + * 调用4参数方法 + * + * @param consumer 4参数Consumer + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer4 consumer, P1 p1, P2 p2, P3 p3, P4 p4) { + Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4); + modifiers.add(c); + return this; + } + + /** + * 调用5参数方法 + * + * @param consumer 5参数Consumer + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @param 参数五类型 + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer5 consumer, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { + Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4, p5); + modifiers.add(c); + return this; + } + + /** + * 构建 + * + * @return 目标对象 + */ + @Override + public T build() { + T value = instantiator.get(); + modifiers.forEach(modifier -> modifier.accept(value)); + modifiers.clear(); + return value; + } + + /** + * 1参数Consumer + */ + @FunctionalInterface + public interface Consumer1 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数二 + */ + void accept(T t, P1 p1); + } + + /** + * 2参数Consumer + */ + @FunctionalInterface + public interface Consumer2 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + */ + void accept(T t, P1 p1, P2 p2); + } + + /** + * 3参数Consumer + */ + @FunctionalInterface + public interface Consumer3 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + */ + void accept(T t, P1 p1, P2 p2, P3 p3); + } + + /** + * 4参数Consumer + */ + @FunctionalInterface + public interface Consumer4 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + */ + void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4); + } + + /** + * 5参数Consumer + */ + @FunctionalInterface + public interface Consumer5 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + */ + void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java new file mode 100644 index 000000000..0ac1cd728 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -0,0 +1,47 @@ +package cn.hutool.core.builder; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.junit.Test; + +/** + * {@link GenericBuilder} 单元测试类 + * + * @author TomXin + */ +public class GenericBuilderTest { + + @Test + public void test() { + Box box = GenericBuilder + .of(Box::new) + .with(Box::setId, 1024L) + .with(Box::setTitle, "Hello World!") + .with(Box::setLength, 9) + .with(Box::setWidth, 8) + .with(Box::setHeight, 7) + .build(); + System.out.println(box); + Box boxModified = GenericBuilder + .of(() -> box) + .with(Box::setTitle, "Hello Friend!") + .with(Box::setLength, 3) + .with(Box::setWidth, 4) + .with(Box::setHeight, 5) + .build(); + System.out.println(boxModified); + } + + @Getter + @Setter + @ToString + public static class Box { + private Long id; + private String title; + private Integer length; + private Integer width; + private Integer height; + } + +} From 54d8356830dd2b216d052662b93b6abca424550b Mon Sep 17 00:00:00 2001 From: zhaoxuyang03 Date: Sat, 29 Jan 2022 21:41:55 +0800 Subject: [PATCH 26/43] =?UTF-8?q?[5.7.21]=20[hutool-core]=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9EcopySafely=E6=96=B9=E6=B3=95=E4=B8=8EmkdirsSafely?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/io/FileUtil.java | 37 ++++++++++++++++++ .../main/java/cn/hutool/core/io/NioUtil.java | 39 ++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 3d4b80858..6fc1f748f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -13,6 +13,7 @@ import cn.hutool.core.io.file.Tailer; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.io.unit.DataSizeUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.CharsetUtil; @@ -537,6 +538,8 @@ public class FileUtil extends PathUtil { } if (file.isDirectory()) { + // TODO: 是否需要统计目录本身的大小呢? + // size += file.length(); long size = 0L; File[] subFiles = file.listFiles(); if (ArrayUtil.isEmpty(subFiles)) { @@ -607,6 +610,7 @@ public class FileUtil extends PathUtil { return null; } if (false == file.exists()) { + // TODO: {@see mkdirsSafely} 确保并发环境下的安全创建 mkParentDirs(file); try { //noinspection ResultOfMethodCallIgnored @@ -827,6 +831,39 @@ public class FileUtil extends PathUtil { return dir; } + /** + * 安全地级联创建目录 (确保并发环境下能创建成功) + * + *
+	 *     并发环境下,假设 test 目录不存在,如果线程A mkdirs "test/A" 目录,线程B mkdirs "test/B"目录,
+	 *     其中一个线程可能会失败,进而导致以下代码抛出 FileNotFoundException 异常
+	 *
+	 *     file.getParentFile().mkdirs(); // 父目录正在被另一个线程创建中,返回 false
+	 *     file.createNewFile(); // 抛出 IO 异常,因为该线程无法感知到父目录已被创建
+	 * 
+ * + * @param dir 待创建的目录 + * @return true表示创建成功,false表示创建失败 + * @since 2022-01-29 + * @author z8g + */ + public static boolean mkdirsSafely(File dir) { + if (dir == null) { + return false; + } + if (dir.isDirectory()) { + return true; + } + for (int i = 1; i <= 5; i++) { // 高并发场景下,可以看到 i 处于 1 ~ 3 之间 + dir.mkdirs(); // 如果文件已存在,也会返回 false,所以该值不能作为是否能创建的依据,因此不对其进行处理 + if (dir.exists()) { + return true; + } + ThreadUtil.sleep(1); + } + return dir.exists(); + } + /** * 创建临时文件
* 创建后的文件名为 prefix[Randon].tmp diff --git a/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java index 2db343457..c247185b2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java @@ -87,12 +87,49 @@ public class NioUtil { Assert.notNull(outChannel, "Out channel is null!"); try { - return inChannel.transferTo(0, inChannel.size(), outChannel); + return copySafely(inChannel, outChannel); } catch (IOException e) { throw new IORuntimeException(e); } } + /** + * 文件拷贝实现 + * + *
+	 * FileChannel#transferTo 或 FileChannel#transferFrom 的实现是平台相关的,需要确保低版本平台的兼容性
+	 * 例如 android 7以下平台在使用 ZipInputStream 解压文件的过程中,
+	 * 通过 FileChannel#transferFrom 传输到文件时,其返回值可能小于 totalBytes,不处理将导致文件内容缺失
+	 *
+	 * // 错误写法,dstChannel.transferFrom 返回值小于 zipEntry.getSize(),导致解压后文件内容缺失
+	 * try (InputStream srcStream = zipFile.getInputStream(zipEntry);
+	 * 		ReadableByteChannel srcChannel = Channels.newChannel(srcStream);
+	 * 		FileOutputStream fos = new FileOutputStream(saveFile);
+	 * 		FileChannel dstChannel = fos.getChannel()) {
+	 * 		dstChannel.transferFrom(srcChannel, 0, zipEntry.getSize());
+	 *  }
+	 * 
+ * + * @param inChannel 输入通道 + * @param outChannel 输出通道 + * @return 输入通道的字节数 + * @throws IOException 发生IO错误 + * @link http://androidxref.com/6.0.1_r10/xref/libcore/luni/src/main/java/java/nio/FileChannelImpl.java + * @link http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java + * @link http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/native/FileChannelImpl.c + * @since 2022-01-29 + * @author z8g + */ + private static long copySafely(FileChannel inChannel, FileChannel outChannel) throws IOException { + long totalBytes = inChannel.size(); + for (long pos = 0, remaining = totalBytes; remaining > 0; ) { // 确保文件内容不会缺失 + long writeBytes = inChannel.transferTo(pos, remaining, outChannel); // 实际传输的字节数 + pos += writeBytes; + remaining -= writeBytes; + } + return totalBytes; + } + /** * 拷贝流,使用NIO,不会关闭channel * From c7a33d90151a884d28e25eb156301a23dc5f3154 Mon Sep 17 00:00:00 2001 From: yucheng Date: Sun, 30 Jan 2022 10:17:00 +0800 Subject: [PATCH 27/43] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E4=BD=8D=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E5=BF=AB=E9=80=9F=E6=B1=82=E8=A7=A3=E5=8F=96=E4=BD=99?= =?UTF-8?q?=E8=BF=90=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/bloomfilter/bitMap/IntMap.java | 8 ++++---- .../main/java/cn/hutool/bloomfilter/bitMap/LongMap.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java index f941d0696..4bda77f63 100644 --- a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java +++ b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/IntMap.java @@ -32,22 +32,22 @@ public class IntMap implements BitMap, Serializable { @Override public void add(long i) { int r = (int) (i / BitMap.MACHINE32); - int c = (int) (i % BitMap.MACHINE32); + int c = (int) (i & (BitMap.MACHINE32 - 1)); ints[r] = ints[r] | (1 << c); } @Override public boolean contains(long i) { int r = (int) (i / BitMap.MACHINE32); - int c = (int) (i % BitMap.MACHINE32); + int c = (int) (i & (BitMap.MACHINE32 - 1)); return ((ints[r] >>> c) & 1) == 1; } @Override public void remove(long i) { int r = (int) (i / BitMap.MACHINE32); - int c = (int) (i % BitMap.MACHINE32); + int c = (int) (i & (BitMap.MACHINE32 - 1)); ints[r] &= ~(1 << c); } -} \ No newline at end of file +} diff --git a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java index 93f0d6d99..7c44325af 100644 --- a/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java +++ b/hutool-bloomFilter/src/main/java/cn/hutool/bloomfilter/bitMap/LongMap.java @@ -32,22 +32,22 @@ public class LongMap implements BitMap, Serializable { @Override public void add(long i) { int r = (int) (i / BitMap.MACHINE64); - long c = i % BitMap.MACHINE64; + long c = i & (BitMap.MACHINE64 - 1); longs[r] = longs[r] | (1L << c); } @Override public boolean contains(long i) { int r = (int) (i / BitMap.MACHINE64); - long c = i % BitMap.MACHINE64; + long c = i & (BitMap.MACHINE64 - 1); return ((longs[r] >>> c) & 1) == 1; } @Override public void remove(long i) { int r = (int) (i / BitMap.MACHINE64); - long c = i % BitMap.MACHINE64; + long c = i & (BitMap.MACHINE64 - 1); longs[r] &= ~(1L << c); } -} \ No newline at end of file +} From c0d2b8c9e38ea39185c7001a2f7936f2d38aaa03 Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Sun, 30 Jan 2022 14:06:43 +0800 Subject: [PATCH 28/43] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=87=8D=E8=BD=BDGener?= =?UTF-8?q?icBuilder=E7=9A=84of=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=9C=89=E5=8F=82=E6=9E=84=E9=80=A0(=E6=9C=80?= =?UTF-8?q?=E5=A4=9A5=E4=B8=AA)=E7=9A=84=E8=B0=83=E7=94=A8;=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=87=8D=E8=BD=BDwith=E6=8E=A5=E5=8F=A3=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=97=A0=E5=8F=82=E6=96=B9=E6=B3=95=E8=B0=83?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hutool/core/builder/GenericBuilder.java | 252 ++++++++++++++++-- .../core/builder/GenericBuilderTest.java | 28 +- 2 files changed, 262 insertions(+), 18 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java index b8da21486..45bde1e3d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -11,25 +11,32 @@ import java.util.function.Supplier; *

使用方法如下:

*
  * Box box = GenericBuilder
- * 		      .of(Box::new)
- * 		      .with(Box::setId, 1024L)
- * 		      .with(Box::setTitle, "Hello World!")
- * 		      .with(Box::setLength, 9)
- * 		      .with(Box::setWidth, 8)
- * 		      .with(Box::setHeight, 7)
- * 		      .build();
+ * 		.of(Box::new)
+ * 		.with(Box::setId, 1024L)
+ * 		.with(Box::setTitle, "Hello World!")
+ * 		.with(Box::setLength, 9)
+ * 		.with(Box::setWidth, 8)
+ * 		.with(Box::setHeight, 7)
+ * 		.build();
  *
  * 
* *

我们也可以对已创建的对象进行修改:

*
  * Box boxModified = GenericBuilder
- * 		      .of(() -> box)
- * 		      .with(Box::setTitle, "Hello Friend!")
- * 		      .with(Box::setLength, 3)
- * 		      .with(Box::setWidth, 4)
- * 		      .with(Box::setHeight, 5)
- * 		      .build();
+ * 		.of(() -> box)
+ * 		.with(Box::setTitle, "Hello Friend!")
+ * 		.with(Box::setLength, 3)
+ * 		.with(Box::setWidth, 4)
+ * 		.with(Box::setHeight, 5)
+ * 		.build();
+ * 
+ *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的

+ *
+ * Box box1 = GenericBuilder
+ * 		.of(Box::new, 2048L, "Hello Partner!", 222, 333, 444)
+ * 		.with(Box::alis)
+ * 		.build();
  * 
* * @author TomXin @@ -43,7 +50,7 @@ public class GenericBuilder implements Builder { private final Supplier instantiator; /** - * 修改器集合 + * 修改器列表 */ private final List> modifiers = new ArrayList<>(); @@ -57,7 +64,7 @@ public class GenericBuilder implements Builder { } /** - * 通过实例化器创建GenericBuilder + * 通过无参数实例化器创建GenericBuilder * * @param instant 实例化器 * @param 目标类型 @@ -67,6 +74,109 @@ public class GenericBuilder implements Builder { return new GenericBuilder<>(instant); } + /** + * 通过1参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param 目标类型 + * @param 参数一类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier1 instant, P1 p1) { + Supplier s = () -> instant.get(p1); + return new GenericBuilder<>(s); + } + + /** + * 通过2参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier2 instant, P1 p1, P2 p2) { + Supplier s = () -> instant.get(p1, p2); + return new GenericBuilder<>(s); + } + + /** + * 通过3参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier3 instant, P1 p1, P2 p2, P3 p3) { + Supplier s = () -> instant.get(p1, p2, p3); + return new GenericBuilder<>(s); + } + + /** + * 通过4参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier4 instant, P1 p1, P2 p2, P3 p3, P4 p4) { + Supplier s = () -> instant.get(p1, p2, p3, p4); + return new GenericBuilder<>(s); + } + + /** + * 通过5参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @param 参数五类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier5 instant, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { + Supplier s = () -> instant.get(p1, p2, p3, p4, p5); + return new GenericBuilder<>(s); + } + + + /** + * 调用无参数方法 + * + * @param consumer 无参数Consumer + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer consumer) { + modifiers.add(consumer); + return this; + } + + /** * 调用1参数方法 * @@ -170,6 +280,118 @@ public class GenericBuilder implements Builder { return value; } + + /** + * 1参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + */ + @FunctionalInterface + public interface Supplier1 { + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @return 目标对象 + */ + T get(P1 p1); + } + + + /** + * 2参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + */ + @FunctionalInterface + public interface Supplier2 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @return 目标对象 + */ + T get(P1 p1, P2 p2); + } + + /** + * 3参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + */ + @FunctionalInterface + public interface Supplier3 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3); + } + + + /** + * 4参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + */ + @FunctionalInterface + public interface Supplier4 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4); + } + + /** + * 5参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @param 参数五类型 + */ + @FunctionalInterface + public interface Supplier5 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); + } + /** * 1参数Consumer */ diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java index 0ac1cd728..b3753e62d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -1,8 +1,7 @@ package cn.hutool.core.builder; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; +import cn.hutool.core.util.StrUtil; +import lombok.*; import org.junit.Test; /** @@ -31,6 +30,11 @@ public class GenericBuilderTest { .with(Box::setHeight, 5) .build(); System.out.println(boxModified); + Box box1 = GenericBuilder + .of(Box::new, 2048L, "Hello Partner!", 222, 333, 444) + .with(Box::alis) + .build(); + System.out.println(box1); } @Getter @@ -42,6 +46,24 @@ public class GenericBuilderTest { private Integer length; private Integer width; private Integer height; + private String titleAlias; + + public Box() { + } + + public Box(Long id, String title, Integer length, Integer width, Integer height) { + this.id = id; + this.title = title; + this.length = length; + this.width = width; + this.height = height; + } + + public void alis() { + if (StrUtil.isNotBlank(this.title)) { + this.titleAlias = "TomXin:\"" + title + "\""; + } + } } } From 7096ef04e01f5af15e959cab41fc7fb0de74f5f6 Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Wed, 2 Feb 2022 11:55:47 +0800 Subject: [PATCH 29/43] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=85=B3=E4=BA=8EGener?= =?UTF-8?q?icBuilder=E7=B1=BB=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/builder/GenericBuilder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java index 45bde1e3d..3046427bd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -31,13 +31,17 @@ import java.util.function.Supplier; * .with(Box::setHeight, 5) * .build(); * - *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的

+ *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的:

*
  * Box box1 = GenericBuilder
  * 		.of(Box::new, 2048L, "Hello Partner!", 222, 333, 444)
  * 		.with(Box::alis)
  * 		.build();
  * 
+ *

注意:本工具类支持调用的方法的参数数量不超过5个,更多的参数不利于阅读和维护。 + * 关于Java方法的参数个数限制似乎并没有明确统一的规范,网络上众说纷纭,这里取个相对平均的数5。 + * 特殊需要求可以基于此类进行拓展. + *

* * @author TomXin * @since jdk1.8 From 6c30ff1e8fc25e93855947bc6cc59cc1134a8193 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 11:31:11 +0800 Subject: [PATCH 30/43] change logo link --- bin/logo.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/logo.sh b/bin/logo.sh index 36a14646a..3366de914 100755 --- a/bin/logo.sh +++ b/bin/logo.sh @@ -7,5 +7,5 @@ echo ' / /_/ // / / // __// __ \ / __ \ / / ' echo ' / __ // /_/ // /_ / /_/ // /_/ // / ' echo '/_/ /_/ \____/ \__/ \____/ \____//_/ ' echo '' -echo '-----------http://hutool.cn/------------' +echo '-----------https://hutool.cn/-----------' echo '========================================' From aca5dc1d3b6a6c025b02ac8b7641cae11a7981ba Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 12:00:30 +0800 Subject: [PATCH 31/43] update dependency --- hutool-db/pom.xml | 10 +++++----- hutool-extra/pom.xml | 8 ++++---- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-system/pom.xml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index b49692e91..4785e323b 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -27,7 +27,7 @@ 3.36.0.3 2.5.2 - 4.0.0 + 4.1.1 @@ -81,7 +81,7 @@ com.github.chris2018998 beecp - 3.3.0 + 3.3.1 slf4j-api @@ -143,13 +143,13 @@ mysql mysql-connector-java - 8.0.27 + 8.0.28 test org.postgresql postgresql - 42.3.1 + 42.3.2 test @@ -173,7 +173,7 @@ ru.yandex.clickhouse clickhouse-jdbc - 0.3.1 + 0.3.2 test diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 4d289fbd1..2f4de10b6 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -23,7 +23,7 @@ 1.4.1 2.3.31 4.9.16 - 3.0.14.RELEASE + 3.0.15.RELEASE 1.6.2 0.1.55 0.32.0 @@ -31,7 +31,7 @@ 3.8.0 5.1.1 4.0.1 - 2.6.2 + 2.6.3 3.3.0 @@ -340,7 +340,7 @@ com.github.houbb pinyin - 0.2.2 + 0.3.1 true @@ -446,7 +446,7 @@ org.springframework spring-expression - 5.3.14 + 5.3.15 compile true diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index db88952d7..9d025a157 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -24,7 +24,7 @@ 2.17.1 1.2 1.3.6 - 3.4.2.Final + 3.4.3.Final 0.43.0 diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 4be7f3f50..6d05e81e3 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -45,7 +45,7 @@ org.ofdrw ofdrw-full - 1.17.6 + 1.17.8 compile true diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index ec3f296fc..ee10d1fef 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -30,7 +30,7 @@ com.github.oshi oshi-core - 6.0.0 + 6.1.0 provided From a79d0c796eeb809d1874a47b248923a729d0747b Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 12:07:59 +0800 Subject: [PATCH 32/43] change to bit op --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46b525879..437715be0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-01-27) +# 5.7.21 (2022-02-04) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 @@ -15,6 +15,7 @@ * 【core 】 DateUtil增加rangeFunc和rangeConsume(issue#I4RSQY@Gitee) * 【core 】 DateTime增加setUseJdkToStringStyle方法 * 【core 】 CharSequenceUtil增加replace重载(issue#2122@Github) +* 【core 】 IntMap和LongMap使用位运算快速求解取余运算(pr#2123@Github) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) From dabb21aad10e5814381a555f8141bdf6d499c500 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 12:43:54 +0800 Subject: [PATCH 33/43] fix test --- .../hutool/core/convert/DateConvertTest.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java index f7ffeac24..41b302ab2 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java @@ -1,15 +1,14 @@ package cn.hutool.core.convert; +import cn.hutool.core.date.DateUtil; +import org.junit.Assert; +import org.junit.Test; + import java.sql.Timestamp; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; -import org.junit.Assert; -import org.junit.Test; - -import cn.hutool.core.date.DateUtil; - public class DateConvertTest { @Test @@ -28,7 +27,7 @@ public class DateConvertTest { int dateLong = -1497600000; Date value = Convert.toDate(dateLong); Assert.assertNotNull(value); - Assert.assertEquals("Mon Dec 15 00:00:00 CST 1969", value.toString()); + Assert.assertTrue(value.toString().startsWith("Mon Dec 15 00:00:00 ")); final java.sql.Date sqlDate = Convert.convert(java.sql.Date.class, dateLong); Assert.assertNotNull(sqlDate); @@ -53,18 +52,18 @@ public class DateConvertTest { java.sql.Date value2 = Convert.convert(java.sql.Date.class, timeLong); Assert.assertEquals(timeLong, value2.getTime()); } - + @Test public void toLocalDateTimeTest() { Date src = new Date(); - + LocalDateTime ldt = Convert.toLocalDateTime(src); Assert.assertEquals(ldt, DateUtil.toLocalDateTime(src)); - + Timestamp ts = Timestamp.from(src.toInstant()); ldt = Convert.toLocalDateTime(ts); Assert.assertEquals(ldt, DateUtil.toLocalDateTime(src)); - + String str = "2020-12-12 12:12:12.0"; ldt = Convert.toLocalDateTime(str); Assert.assertEquals(ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S")), str); From 8cbcf034d3b2c421e33efef9028211ca3f85fe90 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 13:53:15 +0800 Subject: [PATCH 34/43] fix date test --- .../src/test/java/cn/hutool/core/convert/DateConvertTest.java | 2 +- .../src/test/java/cn/hutool/core/date/DateUtilTest.java | 4 ++++ hutool-json/src/test/java/cn/hutool/json/Issue677Test.java | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java index 41b302ab2..e3815d7c0 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/DateConvertTest.java @@ -27,7 +27,7 @@ public class DateConvertTest { int dateLong = -1497600000; Date value = Convert.toDate(dateLong); Assert.assertNotNull(value); - Assert.assertTrue(value.toString().startsWith("Mon Dec 15 00:00:00 ")); + Assert.assertEquals("Mon Dec 15 00:00:00 CST 1969", value.toString().replace("GMT+08:00", "CST")); final java.sql.Date sqlDate = Convert.convert(java.sql.Date.class, dateLong); Assert.assertNotNull(sqlDate); diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 4201009c1..f9009d824 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Console; import cn.hutool.core.util.RandomUtil; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import java.text.SimpleDateFormat; @@ -690,9 +691,12 @@ public class DateUtilTest { } @Test + @Ignore public void parseCSTTest() { String dateStr = "Wed Sep 16 11:26:23 CST 2009"; + // 奇怪的问题,在JDK8_261中,此此测试没有问题,但是升级到311后,结果会不一致,相差一个小时。 + // 猜测可能是默认时区问题 SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); final DateTime parse = DateUtil.parse(dateStr, sdf); diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue677Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue677Test.java index 4cef2f657..b6a041318 100644 --- a/hutool-json/src/test/java/cn/hutool/json/Issue677Test.java +++ b/hutool-json/src/test/java/cn/hutool/json/Issue677Test.java @@ -19,7 +19,7 @@ public class Issue677Test { final String jsonStr = JSONUtil.toJsonStr(dto); final AuditResultDto auditResultDto = JSONUtil.toBean(jsonStr, AuditResultDto.class); - Assert.assertEquals("Mon Dec 15 00:00:00 CST 1969", auditResultDto.getDate().toString()); + Assert.assertEquals("Mon Dec 15 00:00:00 CST 1969", auditResultDto.getDate().toString().replace("GMT+08:00", "CST")); } @Data From d41b864711050cc3c97ab611cfb582ddc6d97fff Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 14:23:02 +0800 Subject: [PATCH 35/43] ignore test --- .../src/test/java/cn/hutool/core/date/DateUtilTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index f9009d824..d61674531 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.BetweenFormatter.Level; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Console; import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.SystemPropsUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -693,10 +694,9 @@ public class DateUtilTest { @Test @Ignore public void parseCSTTest() { + Console.log(SystemPropsUtil.get("java.version")); String dateStr = "Wed Sep 16 11:26:23 CST 2009"; - // 奇怪的问题,在JDK8_261中,此此测试没有问题,但是升级到311后,结果会不一致,相差一个小时。 - // 猜测可能是默认时区问题 SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); final DateTime parse = DateUtil.parse(dateStr, sdf); From d58fc4409af03191f09d6882c2f1cedf2785e6d2 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 14:34:02 +0800 Subject: [PATCH 36/43] fix test --- .../src/test/java/cn/hutool/core/date/DateUtilTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index d61674531..729d19c53 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -5,9 +5,7 @@ import cn.hutool.core.date.BetweenFormatter.Level; import cn.hutool.core.date.format.FastDateFormat; import cn.hutool.core.lang.Console; import cn.hutool.core.util.RandomUtil; -import cn.hutool.core.util.SystemPropsUtil; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import java.text.SimpleDateFormat; @@ -692,12 +690,11 @@ public class DateUtilTest { } @Test - @Ignore public void parseCSTTest() { - Console.log(SystemPropsUtil.get("java.version")); String dateStr = "Wed Sep 16 11:26:23 CST 2009"; SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); final DateTime parse = DateUtil.parse(dateStr, sdf); DateTime dateTime = DateUtil.parseCST(dateStr); From 5ca71c12364752fc2496506fe72433cd8d79345e Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 4 Feb 2022 14:51:23 +0800 Subject: [PATCH 37/43] add comment for test --- hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java index 729d19c53..1e65175fb 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java @@ -692,8 +692,10 @@ public class DateUtilTest { @Test public void parseCSTTest() { String dateStr = "Wed Sep 16 11:26:23 CST 2009"; + Console.log(TimeZone.getDefault().getDisplayName()); SimpleDateFormat sdf = new SimpleDateFormat(DatePattern.JDK_DATETIME_PATTERN, Locale.US); + // Asia/Shanghai是以地区命名的地区标准时,在中国叫CST,因此如果解析CST时不使用"Asia/Shanghai"而使用"GMT+08:00",会导致相差一个小时 sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); final DateTime parse = DateUtil.parse(dateStr, sdf); From 3a9f90c3e2dcc7737512732febed2f7e28654e08 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 10:56:50 +0800 Subject: [PATCH 38/43] add GenericBuilder --- CHANGELOG.md | 3 +- .../hutool/core/builder/GenericBuilder.java | 241 ++---------------- .../hutool/core/exceptions/CheckedUtil.java | 24 +- .../cn/hutool/core/lang/func/Consumer1.java | 32 +++ .../cn/hutool/core/lang/func/Consumer2.java | 36 +++ .../cn/hutool/core/lang/func/Consumer3.java | 38 +++ .../cn/hutool/core/lang/func/Consumer4.java | 41 +++ .../cn/hutool/core/lang/func/Consumer5.java | 44 ++++ .../cn/hutool/core/lang/func/Supplier1.java | 32 +++ .../cn/hutool/core/lang/func/Supplier2.java | 36 +++ .../cn/hutool/core/lang/func/Supplier3.java | 39 +++ .../cn/hutool/core/lang/func/Supplier4.java | 42 +++ .../cn/hutool/core/lang/func/Supplier5.java | 45 ++++ .../core/builder/GenericBuilderTest.java | 24 +- .../core/exceptions/CheckedUtilTest.java | 4 - 15 files changed, 445 insertions(+), 236 deletions(-) create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier1.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier2.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier3.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier4.java create mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier5.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 437715be0..741ef609f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.7.21 (2022-02-04) +# 5.7.21 (2022-02-07) ### 🐣新特性 * 【extra 】 增加jetbrick模板支持 @@ -16,6 +16,7 @@ * 【core 】 DateTime增加setUseJdkToStringStyle方法 * 【core 】 CharSequenceUtil增加replace重载(issue#2122@Github) * 【core 】 IntMap和LongMap使用位运算快速求解取余运算(pr#2123@Github) +* 【core 】 新增通用builder类:GenericBuilder(pr#526@Gitee) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java index 3046427bd..4d4de0de5 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -1,5 +1,16 @@ package cn.hutool.core.builder; +import cn.hutool.core.lang.func.Consumer1; +import cn.hutool.core.lang.func.Consumer2; +import cn.hutool.core.lang.func.Consumer3; +import cn.hutool.core.lang.func.Consumer4; +import cn.hutool.core.lang.func.Consumer5; +import cn.hutool.core.lang.func.Supplier1; +import cn.hutool.core.lang.func.Supplier2; +import cn.hutool.core.lang.func.Supplier3; +import cn.hutool.core.lang.func.Supplier4; +import cn.hutool.core.lang.func.Supplier5; + import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -44,14 +55,14 @@ import java.util.function.Supplier; *

* * @author TomXin - * @since jdk1.8 + * @since 5.7.21 */ public class GenericBuilder implements Builder { /** * 实例化器 */ - private final Supplier instantiator; + private final Supplier instant; /** * 修改器列表 @@ -64,7 +75,7 @@ public class GenericBuilder implements Builder { * @param instant 实例化器 */ public GenericBuilder(Supplier instant) { - this.instantiator = instant; + this.instant = instant; } /** @@ -88,8 +99,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public static GenericBuilder of(Supplier1 instant, P1 p1) { - Supplier s = () -> instant.get(p1); - return new GenericBuilder<>(s); + return of(instant.toSupplier(p1)); } /** @@ -104,8 +114,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public static GenericBuilder of(Supplier2 instant, P1 p1, P2 p2) { - Supplier s = () -> instant.get(p1, p2); - return new GenericBuilder<>(s); + return of(instant.toSupplier(p1, p2)); } /** @@ -122,8 +131,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public static GenericBuilder of(Supplier3 instant, P1 p1, P2 p2, P3 p3) { - Supplier s = () -> instant.get(p1, p2, p3); - return new GenericBuilder<>(s); + return of(instant.toSupplier(p1, p2, p3)); } /** @@ -142,8 +150,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public static GenericBuilder of(Supplier4 instant, P1 p1, P2 p2, P3 p3, P4 p4) { - Supplier s = () -> instant.get(p1, p2, p3, p4); - return new GenericBuilder<>(s); + return of(instant.toSupplier(p1, p2, p3, p4)); } /** @@ -164,8 +171,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public static GenericBuilder of(Supplier5 instant, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - Supplier s = () -> instant.get(p1, p2, p3, p4, p5); - return new GenericBuilder<>(s); + return of(instant.toSupplier(p1, p2, p3, p4, p5)); } @@ -190,8 +196,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public GenericBuilder with(Consumer1 consumer, P1 p1) { - Consumer c = instance -> consumer.accept(instance, p1); - modifiers.add(c); + modifiers.add(consumer.toConsumer(p1)); return this; } @@ -206,8 +211,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public GenericBuilder with(Consumer2 consumer, P1 p1, P2 p2) { - Consumer c = instance -> consumer.accept(instance, p1, p2); - modifiers.add(c); + modifiers.add(consumer.toConsumer(p1, p2)); return this; } @@ -224,8 +228,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public GenericBuilder with(Consumer3 consumer, P1 p1, P2 p2, P3 p3) { - Consumer c = instance -> consumer.accept(instance, p1, p2, p3); - modifiers.add(c); + modifiers.add(consumer.toConsumer(p1, p2, p3)); return this; } @@ -244,8 +247,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public GenericBuilder with(Consumer4 consumer, P1 p1, P2 p2, P3 p3, P4 p4) { - Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4); - modifiers.add(c); + modifiers.add(consumer.toConsumer(p1, p2, p3, p4)); return this; } @@ -266,8 +268,7 @@ public class GenericBuilder implements Builder { * @return GenericBuilder对象 */ public GenericBuilder with(Consumer5 consumer, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4, p5); - modifiers.add(c); + modifiers.add(consumer.toConsumer(p1, p2, p3, p4, p5)); return this; } @@ -278,201 +279,9 @@ public class GenericBuilder implements Builder { */ @Override public T build() { - T value = instantiator.get(); + T value = instant.get(); modifiers.forEach(modifier -> modifier.accept(value)); modifiers.clear(); return value; } - - - /** - * 1参数Supplier - * - * @param 目标类型 - * @param 参数一类型 - */ - @FunctionalInterface - public interface Supplier1 { - /** - * 生成实例的方法 - * - * @param p1 参数一 - * @return 目标对象 - */ - T get(P1 p1); - } - - - /** - * 2参数Supplier - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - */ - @FunctionalInterface - public interface Supplier2 { - - /** - * 生成实例的方法 - * - * @param p1 参数一 - * @param p2 参数二 - * @return 目标对象 - */ - T get(P1 p1, P2 p2); - } - - /** - * 3参数Supplier - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - */ - @FunctionalInterface - public interface Supplier3 { - - /** - * 生成实例的方法 - * - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @return 目标对象 - */ - T get(P1 p1, P2 p2, P3 p3); - } - - - /** - * 4参数Supplier - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @param 参数四类型 - */ - @FunctionalInterface - public interface Supplier4 { - - /** - * 生成实例的方法 - * - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @return 目标对象 - */ - T get(P1 p1, P2 p2, P3 p3, P4 p4); - } - - /** - * 5参数Supplier - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @param 参数四类型 - * @param 参数五类型 - */ - @FunctionalInterface - public interface Supplier5 { - - /** - * 生成实例的方法 - * - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @param p5 参数五 - * @return 目标对象 - */ - T get(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); - } - - /** - * 1参数Consumer - */ - @FunctionalInterface - public interface Consumer1 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数二 - */ - void accept(T t, P1 p1); - } - - /** - * 2参数Consumer - */ - @FunctionalInterface - public interface Consumer2 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - */ - void accept(T t, P1 p1, P2 p2); - } - - /** - * 3参数Consumer - */ - @FunctionalInterface - public interface Consumer3 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - */ - void accept(T t, P1 p1, P2 p2, P3 p3); - } - - /** - * 4参数Consumer - */ - @FunctionalInterface - public interface Consumer4 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - */ - void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4); - } - - /** - * 5参数Consumer - */ - @FunctionalInterface - public interface Consumer5 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @param p5 参数五 - */ - void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/exceptions/CheckedUtil.java b/hutool-core/src/main/java/cn/hutool/core/exceptions/CheckedUtil.java index 876dd0814..f1380a2d0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/exceptions/CheckedUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/exceptions/CheckedUtil.java @@ -51,7 +51,7 @@ public class CheckedUtil { * @param expression Lambda表达式 * @param

运行时传入的参数类型 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func + * @return {@link FuncRt} */ public static FuncRt uncheck(Func expression) { return uncheck(expression, new RuntimeException()); @@ -63,7 +63,7 @@ public class CheckedUtil { * * @param expression 运行时传入的参数类型 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func0 + * @return {@link Func0Rt} */ public static Func0Rt uncheck(Func0 expression) { return uncheck(expression, new RuntimeException()); @@ -76,7 +76,7 @@ public class CheckedUtil { * @param expression 运行时传入的参数类型 * @param

运行时传入的参数类型 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func1 + * @return {@link Func1Rt} */ public static Func1Rt uncheck(Func1 expression) { return uncheck(expression, new RuntimeException()); @@ -89,7 +89,7 @@ public class CheckedUtil { * * @param expression 运行时传入的参数类型 * @param

运行时传入的参数类型 - * @return cn.hutool.core.lang.func.VoidFunc + * @return {@link VoidFuncRt} */ public static

VoidFuncRt

uncheck(VoidFunc

expression) { return uncheck(expression, new RuntimeException()); @@ -100,7 +100,7 @@ public class CheckedUtil { * 如此一来,代码中就不用显示的try-catch转化成运行时异常 * * @param expression 运行时传入的参数类型 - * @return cn.hutool.core.lang.func.VoidFunc0 + * @return {@link VoidFunc0Rt} */ public static VoidFunc0Rt uncheck(VoidFunc0 expression) { return uncheck(expression, new RuntimeException()); @@ -112,7 +112,7 @@ public class CheckedUtil { * * @param expression 运行时传入的参数类型 * @param

运行时传入的参数类型 - * @return cn.hutool.core.lang.func.VoidFunc1 + * @return {@link VoidFunc1Rt} */ public static

VoidFunc1Rt

uncheck(VoidFunc1

expression) { return uncheck(expression, new RuntimeException()); @@ -127,7 +127,7 @@ public class CheckedUtil { * @param rte 期望抛出的运行时异常 * @param

运行时传入的参数类型 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func + * @return {@link FuncRt} */ public static FuncRt uncheck(Func expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); @@ -152,7 +152,7 @@ public class CheckedUtil { * @param expression Lambda表达式 * @param rte 期望抛出的运行时异常 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func0 + * @return {@link Func0Rt} */ public static Func0Rt uncheck(Func0 expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); @@ -178,7 +178,7 @@ public class CheckedUtil { * @param rte 期望抛出的运行时异常 * @param

运行时传入的参数类型 * @param 最终返回的数据类型 - * @return cn.hutool.core.lang.func.Func1 + * @return {@link Func1Rt} */ public static Func1Rt uncheck(Func1 expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); @@ -203,7 +203,7 @@ public class CheckedUtil { * @param expression Lambda表达式 * @param rte 期望抛出的运行时异常 * @param

运行时传入的参数类型 - * @return cn.hutool.core.lang.func.VoidFunc + * @return {@link VoidFuncRt} */ public static

VoidFuncRt

uncheck(VoidFunc

expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); @@ -228,7 +228,7 @@ public class CheckedUtil { * * @param expression Lambda表达式 * @param rte 期望抛出的运行时异常 - * @return cn.hutool.core.lang.func.VoidFunc0 + * @return {@link VoidFunc0Rt} */ public static VoidFunc0Rt uncheck(VoidFunc0 expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); @@ -254,7 +254,7 @@ public class CheckedUtil { * @param expression Lambda表达式 * @param rte 期望抛出的运行时异常 * @param

运行时传入的参数类型 - * @return cn.hutool.core.lang.func.VoidFunc1 + * @return {@link VoidFunc1Rt} */ public static

VoidFunc1Rt

uncheck(VoidFunc1

expression, RuntimeException rte) { Objects.requireNonNull(expression, "expression can not be null"); diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java new file mode 100755 index 000000000..12d4b3893 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java @@ -0,0 +1,32 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Consumer; + +/** + * 1参数Consumer + * + * @param 目标类型 + * @param 参数一类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Consumer1 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数1 + */ + void accept(T t, P1 p1); + + /** + * 将带有参数的Consumer转换为无参{@link Consumer} + * + * @param p1 参数1 + * @return {@link Consumer} + */ + default Consumer toConsumer(P1 p1) { + return instant -> accept(instant, p1); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java new file mode 100755 index 000000000..82c1ea43f --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java @@ -0,0 +1,36 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Consumer; + +/** + * 2参数Consumer + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Consumer2 { + + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + */ + void accept(T t, P1 p1, P2 p2); + + /** + * 将带有参数的Consumer转换为无参{@link Consumer} + * + * @param p1 参数1 + * @param p2 参数2 + * @return {@link Consumer} + */ + default Consumer toConsumer(P1 p1, P2 p2) { + return instant -> accept(instant, p1, p2); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java new file mode 100755 index 000000000..2f5b2eb57 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java @@ -0,0 +1,38 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Consumer; + +/** + * 3参数Consumer + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Consumer3 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + */ + void accept(T t, P1 p1, P2 p2, P3 p3); + + /** + * 将带有参数的Consumer转换为无参{@link Consumer} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @return {@link Consumer} + */ + default Consumer toConsumer(P1 p1, P2 p2, P3 p3) { + return instant -> accept(instant, p1, p2, p3); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java new file mode 100755 index 000000000..59cd66c1e --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java @@ -0,0 +1,41 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Consumer; + +/** + * 4参数Consumer + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Consumer4 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + */ + void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4); + + /** + * 将带有参数的Consumer转换为无参{@link Consumer} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @param p4 参数4 + * @return {@link Consumer} + */ + default Consumer toConsumer(P1 p1, P2 p2, P3 p3, P4 p4) { + return instant -> accept(instant, p1, p2, p3, p4); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java new file mode 100755 index 000000000..be18f3e1f --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java @@ -0,0 +1,44 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Consumer; + +/** + * 5参数Consumer + * + * @param 目标 类型 + * @param 参数一 类型 + * @param 参数二 类型 + * @param 参数三 类型 + * @param 参数四 类型 + * @param 参数五 类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Consumer5 { + /** + * 接收参数方法 + * + * @param t 对象 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + */ + void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); + + /** + * 将带有参数的Consumer转换为无参{@link Consumer} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @param p4 参数4 + * @param p5 参数5 + * @return {@link Consumer} + */ + default Consumer toConsumer(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { + return instant -> accept(instant, p1, p2, p3, p4, p5); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier1.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier1.java new file mode 100755 index 000000000..376c91a2a --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier1.java @@ -0,0 +1,32 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Supplier; + +/** + * 1参数Supplier + * + * @param 目标 类型 + * @param 参数一 类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Supplier1 { + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @return 目标对象 + */ + T get(P1 p1); + + /** + * 将带有参数的Supplier转换为无参{@link Supplier} + * + * @param p1 参数1 + * @return {@link Supplier} + */ + default Supplier toSupplier(P1 p1) { + return () -> get(p1); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier2.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier2.java new file mode 100755 index 000000000..6d5e9ce80 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier2.java @@ -0,0 +1,36 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Supplier; + +/** + * 两个参数的Supplier + * + * @param 目标 类型 + * @param 参数一 类型 + * @param 参数二 类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Supplier2 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @return 目标对象 + */ + T get(P1 p1, P2 p2); + + /** + * 将带有参数的Supplier转换为无参{@link Supplier} + * + * @param p1 参数1 + * @param p2 参数2 + * @return {@link Supplier} + */ + default Supplier toSupplier(P1 p1, P2 p2) { + return () -> get(p1, p2); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier3.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier3.java new file mode 100755 index 000000000..50324e55b --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier3.java @@ -0,0 +1,39 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Supplier; + +/** + * 3参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Supplier3 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3); + + /** + * 将带有参数的Supplier转换为无参{@link Supplier} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @return {@link Supplier} + */ + default Supplier toSupplier(P1 p1, P2 p2, P3 p3) { + return () -> get(p1, p2, p3); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier4.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier4.java new file mode 100755 index 000000000..c715b8693 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier4.java @@ -0,0 +1,42 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Supplier; + +/** + * 4参数Supplier + * + * @param 目标 类型 + * @param 参数一 类型 + * @param 参数二 类型 + * @param 参数三 类型 + * @param 参数四 类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Supplier4 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4); + + /** + * 将带有参数的Supplier转换为无参{@link Supplier} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @param p4 参数4 + * @return {@link Supplier} + */ + default Supplier toSupplier(P1 p1, P2 p2, P3 p3, P4 p4) { + return () -> get(p1, p2, p3, p4); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier5.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier5.java new file mode 100755 index 000000000..121a2ce9c --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/Supplier5.java @@ -0,0 +1,45 @@ +package cn.hutool.core.lang.func; + +import java.util.function.Supplier; + +/** + * 5参数Supplier + * + * @param 目标 类型 + * @param 参数一 类型 + * @param 参数二 类型 + * @param 参数三 类型 + * @param 参数四 类型 + * @param 参数五 类型 + * @author TomXin + * @since 5.7.21 + */ +@FunctionalInterface +public interface Supplier5 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); + + /** + * 将带有参数的Supplier转换为无参{@link Supplier} + * + * @param p1 参数1 + * @param p2 参数2 + * @param p3 参数3 + * @param p4 参数4 + * @param p5 参数5 + * @return {@link Supplier} + */ + default Supplier toSupplier(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { + return () -> get(p1, p2, p3, p4, p5); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java index b3753e62d..f5c8c9732 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -2,6 +2,7 @@ package cn.hutool.core.builder; import cn.hutool.core.util.StrUtil; import lombok.*; +import org.junit.Assert; import org.junit.Test; /** @@ -21,7 +22,13 @@ public class GenericBuilderTest { .with(Box::setWidth, 8) .with(Box::setHeight, 7) .build(); - System.out.println(box); + + Assert.assertEquals(1024L, box.getId().longValue()); + Assert.assertEquals("Hello World!", box.getTitle()); + Assert.assertEquals(9, box.getLength().intValue()); + Assert.assertEquals(8, box.getWidth().intValue()); + Assert.assertEquals(7, box.getHeight().intValue()); + Box boxModified = GenericBuilder .of(() -> box) .with(Box::setTitle, "Hello Friend!") @@ -29,12 +36,23 @@ public class GenericBuilderTest { .with(Box::setWidth, 4) .with(Box::setHeight, 5) .build(); - System.out.println(boxModified); + + Assert.assertEquals(1024L, boxModified.getId().longValue()); + Assert.assertEquals("Hello Friend!", box.getTitle()); + Assert.assertEquals(3, boxModified.getLength().intValue()); + Assert.assertEquals(4, boxModified.getWidth().intValue()); + Assert.assertEquals(5, boxModified.getHeight().intValue()); + Box box1 = GenericBuilder .of(Box::new, 2048L, "Hello Partner!", 222, 333, 444) .with(Box::alis) .build(); - System.out.println(box1); + + Assert.assertEquals(2048L, box1.getId().longValue()); + Assert.assertEquals("Hello Partner!", box1.getTitle()); + Assert.assertEquals(222, box1.getLength().intValue()); + Assert.assertEquals(333, box1.getWidth().intValue()); + Assert.assertEquals(444, box1.getHeight().intValue()); } @Getter diff --git a/hutool-core/src/test/java/cn/hutool/core/exceptions/CheckedUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/exceptions/CheckedUtilTest.java index fbfe82cb2..35be0f241 100644 --- a/hutool-core/src/test/java/cn/hutool/core/exceptions/CheckedUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/exceptions/CheckedUtilTest.java @@ -21,11 +21,8 @@ public class CheckedUtilTest { @Test public void sleepTest() { - VoidFunc0 func = () -> Thread.sleep(1000L); func.callWithRuntimeException(); - - } @@ -39,7 +36,6 @@ public class CheckedUtilTest { } catch (Exception re) { Assert.assertTrue(re instanceof RuntimeException); } - } @SuppressWarnings("ConstantConditions") From d10879c5e98c9b41d285da5726bb0aec5d01f0bc Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 11:01:35 +0800 Subject: [PATCH 39/43] fix code --- .../cn/hutool/json/serialize/JSONWriter.java | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java index c57ef2488..3d6024387 100755 --- a/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java +++ b/hutool-json/src/main/java/cn/hutool/json/serialize/JSONWriter.java @@ -249,22 +249,20 @@ public class JSONWriter extends Writer { * 此方法输出的值不包装引号。 * * @param number 数字 - * @return this */ - private JSONWriter writeNumberValue(Number number) { + private void writeNumberValue(Number number) { // since 5.6.2可配置是否去除末尾多余0,例如如果为true,5.0返回5 final boolean isStripTrailingZeros = null == config || config.isStripTrailingZeros(); - return writeRaw(NumberUtil.toStr(number, isStripTrailingZeros)); + writeRaw(NumberUtil.toStr(number, isStripTrailingZeros)); } /** * 写出Boolean值,直接写出true或false,不适用引号包装 * * @param value Boolean值 - * @return this */ - private JSONWriter writeBooleanValue(Boolean value) { - return writeRaw(value.toString()); + private void writeBooleanValue(Boolean value) { + writeRaw(value.toString()); } /** @@ -273,9 +271,8 @@ public class JSONWriter extends Writer { * 如果toJSONString()返回null,调用toString()方法并使用双引号包装。 * * @param jsonString {@link JSONString} - * @return this */ - private JSONWriter writeJSONStringValue(JSONString jsonString) { + private void writeJSONStringValue(JSONString jsonString) { String valueStr; try { valueStr = jsonString.toJSONString(); @@ -287,7 +284,6 @@ public class JSONWriter extends Writer { } else { writeStrValue(jsonString.toString()); } - return this; } /** @@ -297,30 +293,26 @@ public class JSONWriter extends Writer { * JSON字符串中不能包含控制字符和未经转义的引号和反斜杠 * * @param csq 字符串 - * @return this */ - private JSONWriter writeStrValue(String csq) { + private void writeStrValue(String csq) { try { JSONUtil.quote(csq, writer); } catch (IOException e) { throw new IORuntimeException(e); } - return this; } /** * 写出空格 * * @param count 空格数 - * @return this */ - private JSONWriter writeSpace(int count) { + private void writeSpace(int count) { if (indentFactor > 0) { for (int i = 0; i < count; i++) { writeRaw(CharUtil.SPACE); } } - return this; } /** From a547909d5ed3369e128280e7d1fd9418f771e93b Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 17:00:14 +0800 Subject: [PATCH 40/43] fix code --- .../hutool/core/builder/GenericBuilder.java | 86 ++----------------- .../cn/hutool/core/lang/func/Consumer1.java | 32 ------- .../cn/hutool/core/lang/func/Consumer2.java | 36 -------- .../cn/hutool/core/lang/func/Consumer3.java | 38 -------- .../cn/hutool/core/lang/func/Consumer4.java | 41 --------- .../cn/hutool/core/lang/func/Consumer5.java | 44 ---------- .../core/builder/GenericBuilderTest.java | 6 +- 7 files changed, 10 insertions(+), 273 deletions(-) delete mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java delete mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java delete mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java delete mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java delete mode 100755 hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java index 4d4de0de5..c821ac4b2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -1,10 +1,5 @@ package cn.hutool.core.builder; -import cn.hutool.core.lang.func.Consumer1; -import cn.hutool.core.lang.func.Consumer2; -import cn.hutool.core.lang.func.Consumer3; -import cn.hutool.core.lang.func.Consumer4; -import cn.hutool.core.lang.func.Consumer5; import cn.hutool.core.lang.func.Supplier1; import cn.hutool.core.lang.func.Supplier2; import cn.hutool.core.lang.func.Supplier3; @@ -13,6 +8,7 @@ import cn.hutool.core.lang.func.Supplier5; import java.util.ArrayList; import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -190,85 +186,13 @@ public class GenericBuilder implements Builder { /** * 调用1参数方法 * - * @param consumer 1参数Consumer - * @param p1 参数一 * @param 参数一类型 + * @param consumer 1参数Consumer,一般为Setter方法引用 + * @param p1 参数一 * @return GenericBuilder对象 */ - public GenericBuilder with(Consumer1 consumer, P1 p1) { - modifiers.add(consumer.toConsumer(p1)); - return this; - } - - /** - * 调用2参数方法 - * - * @param consumer 2参数Consumer - * @param p1 参数一 - * @param p2 参数二 - * @param 参数一类型 - * @param 参数二类型 - * @return GenericBuilder对象 - */ - public GenericBuilder with(Consumer2 consumer, P1 p1, P2 p2) { - modifiers.add(consumer.toConsumer(p1, p2)); - return this; - } - - /** - * 调用3参数方法 - * - * @param consumer 3参数Consumer - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @return GenericBuilder对象 - */ - public GenericBuilder with(Consumer3 consumer, P1 p1, P2 p2, P3 p3) { - modifiers.add(consumer.toConsumer(p1, p2, p3)); - return this; - } - - /** - * 调用4参数方法 - * - * @param consumer 4参数Consumer - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @param 参数四类型 - * @return GenericBuilder对象 - */ - public GenericBuilder with(Consumer4 consumer, P1 p1, P2 p2, P3 p3, P4 p4) { - modifiers.add(consumer.toConsumer(p1, p2, p3, p4)); - return this; - } - - /** - * 调用5参数方法 - * - * @param consumer 5参数Consumer - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @param p5 参数五 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @param 参数四类型 - * @param 参数五类型 - * @return GenericBuilder对象 - */ - public GenericBuilder with(Consumer5 consumer, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - modifiers.add(consumer.toConsumer(p1, p2, p3, p4, p5)); + public GenericBuilder with(BiConsumer consumer, P1 p1) { + modifiers.add(instant -> consumer.accept(instant, p1)); return this; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java deleted file mode 100755 index 12d4b3893..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer1.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.hutool.core.lang.func; - -import java.util.function.Consumer; - -/** - * 1参数Consumer - * - * @param 目标类型 - * @param 参数一类型 - * @author TomXin - * @since 5.7.21 - */ -@FunctionalInterface -public interface Consumer1 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数1 - */ - void accept(T t, P1 p1); - - /** - * 将带有参数的Consumer转换为无参{@link Consumer} - * - * @param p1 参数1 - * @return {@link Consumer} - */ - default Consumer toConsumer(P1 p1) { - return instant -> accept(instant, p1); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java deleted file mode 100755 index 82c1ea43f..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer2.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.hutool.core.lang.func; - -import java.util.function.Consumer; - -/** - * 2参数Consumer - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @author TomXin - * @since 5.7.21 - */ -@FunctionalInterface -public interface Consumer2 { - - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - */ - void accept(T t, P1 p1, P2 p2); - - /** - * 将带有参数的Consumer转换为无参{@link Consumer} - * - * @param p1 参数1 - * @param p2 参数2 - * @return {@link Consumer} - */ - default Consumer toConsumer(P1 p1, P2 p2) { - return instant -> accept(instant, p1, p2); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java deleted file mode 100755 index 2f5b2eb57..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer3.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.hutool.core.lang.func; - -import java.util.function.Consumer; - -/** - * 3参数Consumer - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @author TomXin - * @since 5.7.21 - */ -@FunctionalInterface -public interface Consumer3 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - */ - void accept(T t, P1 p1, P2 p2, P3 p3); - - /** - * 将带有参数的Consumer转换为无参{@link Consumer} - * - * @param p1 参数1 - * @param p2 参数2 - * @param p3 参数3 - * @return {@link Consumer} - */ - default Consumer toConsumer(P1 p1, P2 p2, P3 p3) { - return instant -> accept(instant, p1, p2, p3); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java deleted file mode 100755 index 59cd66c1e..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer4.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.hutool.core.lang.func; - -import java.util.function.Consumer; - -/** - * 4参数Consumer - * - * @param 目标类型 - * @param 参数一类型 - * @param 参数二类型 - * @param 参数三类型 - * @param 参数四类型 - * @author TomXin - * @since 5.7.21 - */ -@FunctionalInterface -public interface Consumer4 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - */ - void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4); - - /** - * 将带有参数的Consumer转换为无参{@link Consumer} - * - * @param p1 参数1 - * @param p2 参数2 - * @param p3 参数3 - * @param p4 参数4 - * @return {@link Consumer} - */ - default Consumer toConsumer(P1 p1, P2 p2, P3 p3, P4 p4) { - return instant -> accept(instant, p1, p2, p3, p4); - } -} diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java deleted file mode 100755 index be18f3e1f..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/Consumer5.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.hutool.core.lang.func; - -import java.util.function.Consumer; - -/** - * 5参数Consumer - * - * @param 目标 类型 - * @param 参数一 类型 - * @param 参数二 类型 - * @param 参数三 类型 - * @param 参数四 类型 - * @param 参数五 类型 - * @author TomXin - * @since 5.7.21 - */ -@FunctionalInterface -public interface Consumer5 { - /** - * 接收参数方法 - * - * @param t 对象 - * @param p1 参数一 - * @param p2 参数二 - * @param p3 参数三 - * @param p4 参数四 - * @param p5 参数五 - */ - void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); - - /** - * 将带有参数的Consumer转换为无参{@link Consumer} - * - * @param p1 参数1 - * @param p2 参数2 - * @param p3 参数3 - * @param p4 参数4 - * @param p5 参数5 - * @return {@link Consumer} - */ - default Consumer toConsumer(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { - return instant -> accept(instant, p1, p2, p3, p4, p5); - } -} diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java index f5c8c9732..5ae5fdfce 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -1,7 +1,10 @@ package cn.hutool.core.builder; import cn.hutool.core.util.StrUtil; -import lombok.*; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.experimental.Accessors; import org.junit.Assert; import org.junit.Test; @@ -58,6 +61,7 @@ public class GenericBuilderTest { @Getter @Setter @ToString + @Accessors(chain = true) public static class Box { private Long id; private String title; From da4c1d3bf78a636087bbbc66541fd23226da4b56 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 17:03:05 +0800 Subject: [PATCH 41/43] fix code --- .../src/main/java/cn/hutool/core/builder/GenericBuilder.java | 5 +---- .../test/java/cn/hutool/core/builder/GenericBuilderTest.java | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java index c821ac4b2..829ff54db 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -45,10 +45,7 @@ import java.util.function.Supplier; * .with(Box::alis) * .build(); * - *

注意:本工具类支持调用的方法的参数数量不超过5个,更多的参数不利于阅读和维护。 - * 关于Java方法的参数个数限制似乎并没有明确统一的规范,网络上众说纷纭,这里取个相对平均的数5。 - * 特殊需要求可以基于此类进行拓展. - *

+ *

注意:本工具类支持调用的方法的参数数量不超过1个,更多的参数不利于阅读和维护。

* * @author TomXin * @since 5.7.21 diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java index 5ae5fdfce..84f6d4581 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -32,6 +32,7 @@ public class GenericBuilderTest { Assert.assertEquals(8, box.getWidth().intValue()); Assert.assertEquals(7, box.getHeight().intValue()); + // 对象修改 Box boxModified = GenericBuilder .of(() -> box) .with(Box::setTitle, "Hello Friend!") @@ -46,6 +47,7 @@ public class GenericBuilderTest { Assert.assertEquals(4, boxModified.getWidth().intValue()); Assert.assertEquals(5, boxModified.getHeight().intValue()); + // 多参数构造 Box box1 = GenericBuilder .of(Box::new, 2048L, "Hello Partner!", 222, 333, 444) .with(Box::alis) From bbb12fa22d8661b0a940e760058847c797027480 Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 17:51:53 +0800 Subject: [PATCH 42/43] add method --- CHANGELOG.md | 1 + .../main/java/cn/hutool/core/io/FileUtil.java | 43 +++++++++++++------ .../main/java/cn/hutool/core/io/NioUtil.java | 6 +-- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 741ef609f..6ce31bdb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * 【core 】 CharSequenceUtil增加replace重载(issue#2122@Github) * 【core 】 IntMap和LongMap使用位运算快速求解取余运算(pr#2123@Github) * 【core 】 新增通用builder类:GenericBuilder(pr#526@Gitee) +* 【core 】 新增copySafely方法与mkdirsSafely方法(pr#527@Gitee) ### 🐞Bug修复 * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 6fc1f748f..72eb18ca6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -527,26 +527,39 @@ public class FileUtil extends PathUtil { /** * 计算目录或文件的总大小
* 当给定对象为文件时,直接调用 {@link File#length()}
- * 当给定对象为目录时,遍历目录下的所有文件和目录,递归计算其大小,求和返回 + * 当给定对象为目录时,遍历目录下的所有文件和目录,递归计算其大小,求和返回
+ * 此方法不包括目录本身的占用空间大小。 * * @param file 目录或文件,null或者文件不存在返回0 * @return 总大小,bytes长度 */ public static long size(File file) { + return size(file, false); + } + + /** + * 计算目录或文件的总大小
+ * 当给定对象为文件时,直接调用 {@link File#length()}
+ * 当给定对象为目录时,遍历目录下的所有文件和目录,递归计算其大小,求和返回 + * + * @param file 目录或文件,null或者文件不存在返回0 + * @param includeDirSize 是否包括每层目录本身的大小 + * @return 总大小,bytes长度 + * @since 5.7.21 + */ + public static long size(File file, boolean includeDirSize) { if (null == file || false == file.exists() || isSymlink(file)) { return 0; } if (file.isDirectory()) { - // TODO: 是否需要统计目录本身的大小呢? - // size += file.length(); - long size = 0L; + long size = includeDirSize ? file.length() : 0; File[] subFiles = file.listFiles(); if (ArrayUtil.isEmpty(subFiles)) { return 0L;// empty directory } for (File subFile : subFiles) { - size += size(subFile); + size += size(subFile, includeDirSize); } return size; } else { @@ -610,7 +623,6 @@ public class FileUtil extends PathUtil { return null; } if (false == file.exists()) { - // TODO: {@see mkdirsSafely} 确保并发环境下的安全创建 mkParentDirs(file); try { //noinspection ResultOfMethodCallIgnored @@ -815,7 +827,7 @@ public class FileUtil extends PathUtil { /** * 创建文件夹,会递归自动创建其不存在的父文件夹,如果存在直接返回此文件夹
- * 此方法不对File对象类型做判断,如果File不存在,无法判断其类型 + * 此方法不对File对象类型做判断,如果File不存在,无法判断其类型
* * @param dir 目录 * @return 创建的目录 @@ -825,8 +837,7 @@ public class FileUtil extends PathUtil { return null; } if (false == dir.exists()) { - //noinspection ResultOfMethodCallIgnored - dir.mkdirs(); + mkdirsSafely(dir, 5, 1); } return dir; } @@ -843,23 +854,27 @@ public class FileUtil extends PathUtil { * * * @param dir 待创建的目录 + * @param tryCount 最大尝试次数 + * @param sleepMillis 线程等待的毫秒数 * @return true表示创建成功,false表示创建失败 - * @since 2022-01-29 + * @since 5.7.21 * @author z8g */ - public static boolean mkdirsSafely(File dir) { + public static boolean mkdirsSafely(File dir, int tryCount, long sleepMillis) { if (dir == null) { return false; } if (dir.isDirectory()) { return true; } - for (int i = 1; i <= 5; i++) { // 高并发场景下,可以看到 i 处于 1 ~ 3 之间 - dir.mkdirs(); // 如果文件已存在,也会返回 false,所以该值不能作为是否能创建的依据,因此不对其进行处理 + for (int i = 1; i <= tryCount; i++) { // 高并发场景下,可以看到 i 处于 1 ~ 3 之间 + // 如果文件已存在,也会返回 false,所以该值不能作为是否能创建的依据,因此不对其进行处理 + //noinspection ResultOfMethodCallIgnored + dir.mkdirs(); if (dir.exists()) { return true; } - ThreadUtil.sleep(1); + ThreadUtil.sleep(sleepMillis); } return dir.exists(); } diff --git a/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java index c247185b2..806105051 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/NioUtil.java @@ -117,13 +117,13 @@ public class NioUtil { * @link http://androidxref.com/6.0.1_r10/xref/libcore/luni/src/main/java/java/nio/FileChannelImpl.java * @link http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/java/sun/nio/ch/FileChannelImpl.java * @link http://androidxref.com/7.0.0_r1/xref/libcore/ojluni/src/main/native/FileChannelImpl.c - * @since 2022-01-29 * @author z8g + * @since 5.7.21 */ private static long copySafely(FileChannel inChannel, FileChannel outChannel) throws IOException { - long totalBytes = inChannel.size(); + final long totalBytes = inChannel.size(); for (long pos = 0, remaining = totalBytes; remaining > 0; ) { // 确保文件内容不会缺失 - long writeBytes = inChannel.transferTo(pos, remaining, outChannel); // 实际传输的字节数 + final long writeBytes = inChannel.transferTo(pos, remaining, outChannel); // 实际传输的字节数 pos += writeBytes; remaining -= writeBytes; } From d5916b9998015346cbddb80c52de90fdfe5cad6c Mon Sep 17 00:00:00 2001 From: Looly Date: Mon, 7 Feb 2022 19:04:37 +0800 Subject: [PATCH 43/43] fix bug --- CHANGELOG.md | 1 + hutool-dfa/pom.xml | 5 --- .../java/cn/hutool/dfa/SensitiveUtil.java | 19 ++++++++--- .../src/main/java/cn/hutool/dfa/WordTree.java | 12 +++---- .../src/test/java/cn/hutool/dfa/DfaTest.java | 33 ++++++++++++++++--- .../java/cn/hutool/dfa/SensitiveUtilTest.java | 26 ++++++--------- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ce31bdb6..6686d2456 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * 【core 】 修复ChineseDate农历获取正月出现数组越界BUG(issue#2112@Github) * 【extra 】 修复EmojiUtil.toHtmlHex()方法(pr#519@Gitee) * 【system 】 修复CpuInfo.getUsed()方法(issue#2116@Github) +* 【dfa 】 修复密集匹配和贪婪匹配冲突问题(issue#2126@Github) ------------------------------------------------------------------------------------------------------------- # 5.7.20 (2022-01-20) diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 6416c6f74..3e05431b2 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -17,11 +17,6 @@ Hutool 基于DFA的关键词查找 - - cn.hutool - hutool-core - ${project.parent.version} - cn.hutool hutool-json diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java b/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java index 0c2584690..bcf81a784 100644 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/SensitiveUtil.java @@ -195,11 +195,21 @@ public final class SensitiveUtil { */ public static T sensitiveFilter(T bean, boolean isGreedMatch, SensitiveProcessor sensitiveProcessor) { String jsonText = JSONUtil.toJsonStr(bean); - @SuppressWarnings("unchecked") - final Class c = (Class) bean.getClass(); + @SuppressWarnings("unchecked") final Class c = (Class) bean.getClass(); return JSONUtil.toBean(sensitiveFilter(jsonText, isGreedMatch, sensitiveProcessor), c); } + /** + * 处理过滤文本中的敏感词,默认替换成* + * + * @param text 文本 + * @return 敏感词过滤处理后的文本 + * @since 5.7.21 + */ + public static String sensitiveFilter(String text) { + return sensitiveFilter(text, true, null); + } + /** * 处理过滤文本中的敏感词,默认替换成* * @@ -214,13 +224,14 @@ public final class SensitiveUtil { } //敏感词过滤场景下,不需要密集匹配 - List foundWordList = getFoundAllSensitive(text, false, isGreedMatch); + List foundWordList = getFoundAllSensitive(text, true, isGreedMatch); if (CollUtil.isEmpty(foundWordList)) { return text; } sensitiveProcessor = sensitiveProcessor == null ? new SensitiveProcessor() { } : sensitiveProcessor; - Map foundWordMap = new HashMap<>(foundWordList.size()); + + final Map foundWordMap = new HashMap<>(foundWordList.size(), 1); foundWordList.forEach(foundWord -> foundWordMap.put(foundWord.getStartIndex(), foundWord)); int length = text.length(); StringBuilder textStringBuilder = new StringBuilder(); diff --git a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java index 310f5958b..a58371707 100644 --- a/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java +++ b/hutool-dfa/src/main/java/cn/hutool/dfa/WordTree.java @@ -3,7 +3,6 @@ package cn.hutool.dfa; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Filter; -import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.StrUtil; import java.util.ArrayList; @@ -247,15 +246,15 @@ public class WordTree extends HashMap { List foundWords = new ArrayList<>(); WordTree current = this; - int length = text.length(); + final int length = text.length(); final Filter charFilter = this.charFilter; //存放查找到的字符缓存。完整出现一个词时加到findedWords中,否则清空 - final StrBuilder wordBuffer = StrUtil.strBuilder(); - final StrBuilder keyBuffer = StrUtil.strBuilder(); + final StringBuilder wordBuffer = StrUtil.builder(); + final StringBuilder keyBuffer = StrUtil.builder(); char currentChar; for (int i = 0; i < length; i++) { - wordBuffer.reset(); - keyBuffer.reset(); + wordBuffer.setLength(0); + keyBuffer.setLength(0); for (int j = i; j < length; j++) { currentChar = text.charAt(j); // Console.log("i: {}, j: {}, currentChar: {}", i, j, currentChar); @@ -284,6 +283,7 @@ public class WordTree extends HashMap { if (false == isDensityMatch) { //如果非密度匹配,跳过匹配到的词 i = j; + break; } if (false == isGreedMatch) { //如果懒惰匹配(非贪婪匹配)。当遇到第一个结尾标记就结束本轮匹配 diff --git a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java index d466f69b7..f185fac31 100644 --- a/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java +++ b/hutool-dfa/src/test/java/cn/hutool/dfa/DfaTest.java @@ -47,7 +47,7 @@ public class DfaTest { } /** - * 贪婪匹配原则测试 + * 贪婪非密集匹配原则测试 */ @Test public void greedMatchTest() { @@ -56,15 +56,15 @@ public class DfaTest { // ----------------------------------------------------------------------------------------------------------------------------------- // 情况三:匹配到最长关键词,跳过已经匹配的关键词 - // 匹配到【大】,由于到最长匹配,因此【大土豆】接着被匹配 - // 由于【大土豆】被匹配,【土豆】被跳过,由于【刚出锅】被匹配,【出锅】被跳过 + // 匹配到【大】,由于非密集匹配,因此从下一个字符开始查找,匹配到【土豆】接着被匹配 + // 由于【刚出锅】被匹配,由于非密集匹配,【出锅】被跳过 List matchAll = tree.matchAll(text, -1, false, true); - Assert.assertEquals(matchAll, CollUtil.newArrayList("大", "大土^豆", "刚出锅")); + Assert.assertEquals(matchAll, CollUtil.newArrayList("大", "土^豆", "刚出锅")); } /** - * 密集匹配原则(最短匹配)和贪婪匹配原则测试 + * 密集匹配原则(最长匹配)和贪婪匹配原则测试 */ @Test public void densityAndGreedMatchTest() { @@ -80,6 +80,29 @@ public class DfaTest { } + @Test + public void densityAndGreedMatchTest2(){ + WordTree tree = new WordTree(); + tree.addWord("赵"); + tree.addWord("赵阿"); + tree.addWord("赵阿三"); + + final List result = tree.matchAllWords("赵阿三在做什么", -1, true, true); + Assert.assertEquals(3, result.size()); + + Assert.assertEquals("赵", result.get(0).getWord()); + Assert.assertEquals(0, result.get(0).getStartIndex().intValue()); + Assert.assertEquals(0, result.get(0).getEndIndex().intValue()); + + Assert.assertEquals("赵阿", result.get(1).getWord()); + Assert.assertEquals(0, result.get(1).getStartIndex().intValue()); + Assert.assertEquals(1, result.get(1).getEndIndex().intValue()); + + Assert.assertEquals("赵阿三", result.get(2).getWord()); + Assert.assertEquals(0, result.get(2).getStartIndex().intValue()); + Assert.assertEquals(2, result.get(2).getEndIndex().intValue()); + } + /** * 停顿词测试 */ diff --git a/hutool-dfa/src/test/java/cn/hutool/dfa/SensitiveUtilTest.java b/hutool-dfa/src/test/java/cn/hutool/dfa/SensitiveUtilTest.java index ba7348b09..5bbbe9f23 100644 --- a/hutool-dfa/src/test/java/cn/hutool/dfa/SensitiveUtilTest.java +++ b/hutool-dfa/src/test/java/cn/hutool/dfa/SensitiveUtilTest.java @@ -1,5 +1,7 @@ package cn.hutool.dfa; +import cn.hutool.core.collection.ListUtil; +import lombok.Data; import org.junit.Assert; import org.junit.Test; @@ -24,25 +26,17 @@ public class SensitiveUtilTest { Assert.assertEquals(bean.getStr(), "我有一颗$****,***的"); } + @Data public static class TestBean { private String str; private Integer num; - - public String getStr() { - return str; - } - - public void setStr(String str) { - this.str = str; - } - - public Integer getNum() { - return num; - } - - public void setNum(Integer num) { - this.num = num; - } } + @Test + public void issue2126(){ + SensitiveUtil.init(ListUtil.of("赵", "赵阿", "赵阿三")); + + String result = SensitiveUtil.sensitiveFilter("赵阿三在做什么。", true, null); + Assert.assertEquals("***在做什么。", result); + } }