项目场景:
有一组顺序错乱的字符串如下:
附件1、附件1-2、附件1-1-2、附件1-12、附件1-1、附件1-2-1、附件1-2-13、附件1-155
通过字符串对比排序:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("附件1");
list.add("附件1-2");
list.add("附件1-1-2");
list.add("附件1-12");
list.add("附件1-1");
list.add("附件1-2-1");
list.add("附件1-2-13");
list.add("附件1-155");
Collections.sort(list, Comparator.naturalOrder());
for (String s : list) {
System.out.println(s);
}
}
打印结果
跟期望结果不一样 ,期望的结果应该是大的数字在后面
附件1
附件1-1
附件1-1-2
附件1-12
附件1-2
附件1-2-1
附件1-2-13
附件1-155
解决方案:
思路:字符串排序,如果前面的字符都不一致,那么还没到数值部分就已经排好序了,就不需要再对比数值了。前面的字符相同,后面按照我们的预期排序的话,我们就需要将数值提取出来,按照数值大小做对比就可以了。
具体代码:
package com.test.services;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SortService {
/**
* 包含数字的字符串进行比较(按照从小到大排序)
*/
public static Integer compareString(String string1, String string2) {
//拆分两个字符串
List<String> list1 = splitString(string1);
List<String> list2 = splitString(string2);
//依次对比拆分出的每个值
int index = 0;
while (true) {
//相等表示两个字符串完全相等
if (index >= Math.max(list1.size(), list2.size())) {
return 0;
}
String str1 = null;
if (index < list1.size()){
str1 = list1.get(index);
}else{
str1 = "";
}
String str2 = null;
if (index < list2.size()){
str2 = list2.get(index);
}else{
str2 = "";
}
//字符串相等则继续判断下一组数据
if (str1.equals(str2)) {
index++;
continue;
}
//是纯数字,比较数字大小
if (isNum(str1) && isNum(str2)) {
if(Integer.parseInt(str1) < Integer.parseInt(str2)){
return -1;
}else{
return 1;
}
}
// 如果最后为空
if(str1.equals("")){
return -1;
}else if(str2.equals("")){
return 1;
}
// 字符串比较大小
if(str1.compareTo(str2)>0){
return -1;
}else{
return 1;
}
}
}
/**
* 是否是纯数字
*/
private static Boolean isNum(String str){
return Pattern.compile("\\d+").matcher(str).matches();
}
/**
* 拆分字符串
* 输入:第5章第100节课
* 返回:[第,5,章第,100,节课]
*/
private static List<String> splitString(String str){
List<String> list = new ArrayList<>();
if(str == null){
return list;
}
Matcher matcher = Pattern.compile("([^0-9]+)|(\\d+)").matcher(str.replaceAll(" ",""));
while (matcher.find()) {
list.add(matcher.group());
}
return list;
}
}
测试代码
1.字符串集合
package com.test.services;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestService {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("附件1");
list.add("附件1-1");
list.add("附件1-12");
list.add("附件1-1-1");
list.add("附件1-1-13");
list.add("附件1-2");
list.add("附件1-2-1");
list.add("附件1-2-13");
list.add("附件2");
list.add("附件2-1");
list.add("附件2-12");
list.add("附件2-1-1");
list.add("附件2-1-13");
list.add("附件2-2");
list.add("附件2-2-1");
list.add("附件2-2-13");
Collections.sort(list,(o1, o2) -> SortService.compareString(o1, o2));
for (String s : list) {
System.out.println(s);
}
}
}
2.对象集合
测试对象实体:
package com.test.services;
import lombok.Data;
@Data
public class TestVo {
private Integer id;
private String name;
public TestVo(Integer id, String name) {
this.id = id;
this.name = name;
}
}
package com.test.services;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Test1Service {
public static void main(String[] args) {
List<TestVo> tests = new ArrayList<>();
tests.add(new TestVo(0,"附件1"));
tests.add(new TestVo(1,"附件1-1"));
tests.add(new TestVo(2,"附件1-12"));
tests.add(new TestVo(3,"附件1-1-1"));
tests.add(new TestVo(4,"附件1-1-13"));
tests.add(new TestVo(5,"附件1-2"));
tests.add(new TestVo(6,"附件1-2-1"));
tests.add(new TestVo(7,"附件1-2-13"));
tests.add(new TestVo(8,"附件2"));
tests.add(new TestVo(9,"附件2-1"));
tests.add(new TestVo(10,"附件2-12"));
tests.add(new TestVo(11,"附件2-1-1"));
tests.add(new TestVo(12,"附件2-1-13"));
tests.add(new TestVo(13,"附件2-2"));
tests.add(new TestVo(14,"附件2-2-1"));
tests.add(new TestVo(15,"附件2-2-13"));
List<TestVo> collect = tests
.stream()
.sorted((o1, o2) -> SortService.compareString(o1.getName(), o2.getName()))
.collect(Collectors.toList());
for (TestVo testVo : collect) {
System.out.println(testVo.getName());
}
}
}
打印结果: