Java排序算法之名称首字母排序实现过程实战

发布日期 2023-10-24 22:32:01 已于 2023-10-24 23:13:48 修改

最近项目中有个排行榜,需要将用户名称按成绩得分进行从大到小排序展示,而且如果得分相同,则需要按用户名称拼音首字母顺序排列,比如阿文、巴璐的得分都是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!到这里就已经实现最终需求了,再看一下排行榜展示效果如下: