说明:
- 使用java中的Collections.sort()方法进行排序,主要部分在于实现的StrComparatorUtils根据集合中对象的字符串类型字段进行排序。
- 主要是解决字符串中即包含字母又包含字符串的情况下,排序不准确的问题。
1、测试方法
public class SortTest {
public static void main(String[] args) {
List<SortDto> sortDtoList = new ArrayList<>();
sortDtoList.add(new SortDto("a2hang", 1));
sortDtoList.add(new SortDto("d1", 1));
sortDtoList.add(new SortDto());
sortDtoList.add(new SortDto("1d", 1));
// 主要方法就是StrComparatorUtils类
// 传入的参数中"name"为需要排序的字段名称(必须是字符串类型),第二个参数是“是否倒叙排列”
Collections.sort(sortDtoList, new StrComparatorUtils("name",false));
for (SortDto sortDto : sortDtoList) {
System.out.println(sortDto.toString());
}
}
}
输出结果
SortDomain{name='null', age=null}
SortDomain{name='1d', age=1}
SortDomain{name='a2hang', age=1}
SortDomain{name='d1', age=1}
2、字符串比较工具类
/**
* 根据传入类的属性进行排序
* 说明:属性必须是字符串类型
*/
public class StrComparatorUtils<T> implements Comparator<T> {
private String str1, str2;
private int pos1, pos2, len1, len2;
// 传入类中需要比较的字段
private String propertyName;
private boolean isDesc = false;
/**
* 传入对象的属性名,根据该属性值进行排序
* @param propertyName
*/
public StrComparatorUtils(String propertyName) {
this.propertyName = propertyName;
}
/**
* 传入对象的属性名,根据该属性值进行排序
* @param propertyName
* @param isDesc 是否倒序,默认为false
*/
public StrComparatorUtils(String propertyName, boolean isDesc) {
this.propertyName = propertyName;
this.isDesc = isDesc;
}
public int compare(T o1, T o2) {
if (isDesc) {
str2 = getPropertyValue(o1);
str1 = getPropertyValue(o2);
} else {
str1 = getPropertyValue(o1);
str2 = getPropertyValue(o2);
}
len1 = str1.length();
len2 = str2.length();
pos1 = pos2 = 0;
int result = 0;
while (result == 0 && pos1 < len1 && pos2 < len2) {
char ch1 = str1.charAt(pos1);
char ch2 = str2.charAt(pos2);
if (Character.isDigit(ch1)) {
result = Character.isDigit(ch2) ? compareNumbers() : -1;
} else if (Character.isLetter(ch1)) {
result = Character.isLetter(ch2) ? compareOther(true) : 1;
} else {
result = Character.isDigit(ch2) ? 1
: Character.isLetter(ch2) ? -1
: compareOther(false);
}
pos1++;
pos2++;
}
return result == 0 ? len1 - len2 : result;
}
private String getPropertyValue(T o1) {
String str = "";
try {
Field field = o1.getClass().getDeclaredField(propertyName);
field.setAccessible(true);
Object obj = field.get(o1);
if (obj != null){
return obj.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
private int compareNumbers() {
int end1 = pos1 + 1;
while (end1 < len1 && Character.isDigit(str1.charAt(end1))) {
end1++;
}
int fullLen1 = end1 - pos1;
while (pos1 < end1 && str1.charAt(pos1) == '0') {
pos1++;
}
int end2 = pos2 + 1;
while (end2 < len2 && Character.isDigit(str2.charAt(end2))) {
end2++;
}
int fullLen2 = end2 - pos2;
while (pos2 < end2 && str2.charAt(pos2) == '0') {
pos2++;
}
int delta = (end1 - pos1) - (end2 - pos2);
if (delta != 0) {
return delta;
}
while (pos1 < end1 && pos2 < end2) {
delta = str1.charAt(pos1++) - str2.charAt(pos2++);
if (delta != 0) {
return delta;
}
}
pos1--;
pos2--;
return fullLen2 - fullLen1;
}
private int compareOther(boolean isLetters) {
char ch1 = str1.charAt(pos1);
char ch2 = str2.charAt(pos2);
if (ch1 == ch2) {
return 0;
}
if (isLetters) {
ch1 = Character.toUpperCase(ch1);
ch2 = Character.toUpperCase(ch2);
if (ch1 != ch2) {
ch1 = Character.toLowerCase(ch1);
ch2 = Character.toLowerCase(ch2);
}
}
return ch1 - ch2;
}
}
3、测试实体类
public class SortDto {
private String name;
private Integer age;
public SortDto() {
}
public SortDto(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "SortDomain{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}