最近项目中有个排行榜,需要将用户名称按成绩得分进行从大到小排序展示,而且如果得分相同,则需要按用户名称拼音首字母顺序排列,比如阿文、巴璐的得分都是92,那么阿文需要排在巴璐的前面,因为A < B。
目前的展示情况如下:
可以看到得分都是0的情况下,它是没有按照名称首字母顺序排列的。接下来将借助pinyin4j将名称转成汉语拼音,然后实现最终需求,pinyin4j也是解决这个问题的关键,pinyin4j官网地址:http://pinyin4j.sourceforge.net
首先需要在父工程的pom.xml文件中定义pinyin4j的版本号属性:
<pinyin4j.version>2.5.0</pinyin4j.version>
接着同样在父工程中配置pinyin4j依赖:
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>${pinyin4j.version}</version>
</dependency>
然后再来改造我们原来的代码,原来代码如下:
result.setSectionManagerAllRankings(sectionManagerAllRankings.stream()
// 按得分从大到小排列
.sorted(Comparator.comparing(AssScoreTopRanking.SectionManagerAllRanking::getScore)
.reversed()
.collect(Collectors.toList()));
可以看到原来代码只是按照得分从大到小排序了,现在只需要追加一个比较器即可,修改后的代码如下:
result.setSectionManagerAllRankings(sectionManagerAllRankings.stream()
// 按得分从大到小排列
.sorted(Comparator.comparing(AssScoreTopRanking.SectionManagerAllRanking::getScore)
.reversed()
.thenComparing(new NameHeadCharComparator<>()))
.collect(Collectors.toList()));
可以看到增加了一个比较器NameHeadCharComparator,它的实现代码如下:
import net.sourceforge.pinyin4j.PinyinHelper;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
/**
* @description 自定义比较器, 比较规则: 按名称首字母从小到大
* @author xinzk
* @date 2023/10/23 10:34
*/
public class NameHeadCharComparator<T> implements Comparator<T> {
@Override
public int compare(T o1, T o2) {
try {
Method method = o1.getClass().getMethod("getName");
String name1 = (String)method.invoke(o1);
String name2 = (String)method.invoke(o2);
if (StringUtils.isNotEmpty(name1) && StringUtils.isNotEmpty(name2)) {
String[] p1 = PinyinHelper.toHanyuPinyinStringArray(name1.charAt(0));
String[] p2 = PinyinHelper.toHanyuPinyinStringArray(name2.charAt(0));
char c1 = Arrays.stream(p1).findFirst().get().substring(0, 1).charAt(0);
char c2 = Arrays.stream(p2).findFirst().get().substring(0, 1).charAt(0);
return String.valueOf(c1).compareTo(String.valueOf(c2));
} else {
return 0;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
OK!到这里就已经实现最终需求了,再看一下排行榜展示效果如下: