diff --git a/hutool-core/src/main/java/cn/hutool/core/comparator/WindowsExplorerStringComparator.java b/hutool-core/src/main/java/cn/hutool/core/comparator/WindowsExplorerStringComparator.java
new file mode 100644
index 000000000..1b3d36eba
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/comparator/WindowsExplorerStringComparator.java
@@ -0,0 +1,80 @@
+package cn.hutool.core.comparator;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Windows 资源管理器风格字符串比较器
+ *
+ *
此比较器模拟了 Windows 资源管理器的文件名排序方式,可得到与其相同的排序结果。
+ *
+ * 假设有一个数组,包含若干个文件名 {@code {"abc2.doc", "abc1.doc", "abc12.doc"}}
+ * 在 Windows 资源管理器中以名称排序时,得到 {@code {"abc1.doc", "abc2.doc", "abc12.doc" }}
+ * 调用 {@code Arrays.sort(filenames);} 时,得到 {@code {"abc1.doc", "abc12.doc", "abc2.doc" }}
+ * 调用 {@code Arrays.sort(filenames, new WindowsExplorerStringComparator());} 时,得到 {@code {"abc1.doc", "abc2.doc",
+ * "abc12.doc" }},这与在资源管理器中看到的相同
+ *
+ * @author YMNNs
+ * @see
+ * Java - Sort Strings like Windows Explorer
+ */
+public class WindowsExplorerStringComparator implements Comparator {
+
+ private static final Pattern splitPattern = Pattern.compile("\\d+|\\.|\\s");
+
+ @Override
+ public int compare(String str1, String str2) {
+ Iterator i1 = splitStringPreserveDelimiter(str1).iterator();
+ Iterator i2 = splitStringPreserveDelimiter(str2).iterator();
+ while (true) {
+ //Til here all is equal.
+ if (!i1.hasNext() && !i2.hasNext()) {
+ return 0;
+ }
+ //first has no more parts -> comes first
+ if (!i1.hasNext()) {
+ return -1;
+ }
+ //first has more parts than i2 -> comes after
+ if (!i2.hasNext()) {
+ return 1;
+ }
+
+ String data1 = i1.next();
+ String data2 = i2.next();
+ int result;
+ try {
+ //If both data are numbers, then compare numbers
+ result = Long.compare(Long.parseLong(data1), Long.parseLong(data2));
+ //If numbers are equal than longer comes first
+ if (result == 0) {
+ result = -Integer.compare(data1.length(), data2.length());
+ }
+ } catch (NumberFormatException ex) {
+ //compare text case insensitive
+ result = data1.compareToIgnoreCase(data2);
+ }
+
+ if (result != 0) {
+ return result;
+ }
+ }
+ }
+
+ private List splitStringPreserveDelimiter(String str) {
+ Matcher matcher = splitPattern.matcher(str);
+ List list = new ArrayList<>();
+ int pos = 0;
+ while (matcher.find()) {
+ list.add(str.substring(pos, matcher.start()));
+ list.add(matcher.group());
+ pos = matcher.end();
+ }
+ list.add(str.substring(pos));
+ return list;
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/comparator/WindowsExplorerStringComparatorTest.java b/hutool-core/src/test/java/cn/hutool/core/comparator/WindowsExplorerStringComparatorTest.java
new file mode 100644
index 000000000..1dc9beffb
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/comparator/WindowsExplorerStringComparatorTest.java
@@ -0,0 +1,71 @@
+package cn.hutool.core.comparator;
+
+import cn.hutool.core.lang.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@link WindowsExplorerStringComparator} 单元测试类
+ *
+ * @author YMNNs
+ */
+public class WindowsExplorerStringComparatorTest {
+
+ List answer1 = new ArrayList() {{
+ add("filename");
+ add("filename 00");
+ add("filename 0");
+ add("filename 01");
+ add("filename.jpg");
+ add("filename.txt");
+ add("filename00.jpg");
+ add("filename00a.jpg");
+ add("filename00a.txt");
+ add("filename0");
+ add("filename0.jpg");
+ add("filename0a.txt");
+ add("filename0b.jpg");
+ add("filename0b1.jpg");
+ add("filename0b02.jpg");
+ add("filename0c.jpg");
+ add("filename01.0hjh45-test.txt");
+ add("filename01.0hjh46");
+ add("filename01.1hjh45.txt");
+ add("filename01.hjh45.txt");
+ add("Filename01.jpg");
+ add("Filename1.jpg");
+ add("filename2.hjh45.txt");
+ add("filename2.jpg");
+ add("filename03.jpg");
+ add("filename3.jpg");
+ }};
+
+ List answer2 = new ArrayList() {{
+ add("abc1.doc");
+ add("abc2.doc");
+ add("abc12.doc");
+ }};
+
+ @Test
+ public void testCompare1() {
+ List toSort = new ArrayList<>(answer1);
+ while (toSort.equals(answer1)) {
+ Collections.shuffle(toSort);
+ }
+ toSort.sort(new WindowsExplorerStringComparator());
+ Assert.equals(toSort, answer1);
+ }
+
+ @Test
+ public void testCompare2() {
+ List toSort = new ArrayList<>(answer2);
+ while (toSort.equals(answer2)) {
+ Collections.shuffle(toSort);
+ }
+ toSort.sort(new WindowsExplorerStringComparator());
+ Assert.equals(toSort, answer2);
+ }
+}