精华内容
下载资源
问答
  • 2019-09-25 10:07:14

    `java实现最近搜索词条`

    首先先在项目中部署好redis,部署好之后多的话就不说了,直接搬出代码实现:

    //首先注入RedisTemplate
    private RedisTemplate<Object, Object> template;
    
    
    //入参每次搜索时输入的字符串,每次都放入ZSet中
    if (StringUtils.isNotBlank(searchStr)) {
                //将查询参数添加到redis的zset中
                template.opsForZSet().incrementScore("hwords", searchStr, 1);
            }
    
    
    //获取热词
    public List getRedisScoreMaxVal() {
            List list = new ArrayList();
            //参数1(redis的K值),参数2(从第几条开始),参数3(从0开始截取多少位)
            Set<ZSetOperations.TypedTuple<Object>> typedTupleSet = template.opsForZSet().reverseRangeWithScores("hwords", 0, 4);
            Iterator iterator = typedTupleSet.iterator();
            while (iterator.hasNext()) {
                ZSetOperations.TypedTuple<Object> typedTuple = (ZSetOperations.TypedTuple<Object>) iterator.next();
                Object value = typedTuple.getValue();
                //获取score值
                double score = typedTuple.getScore();
                list.add(value);
            }
            return list;
        }
    

    这样就实现了通过redis获取热词。

    更多相关内容
  • Java热搜问题大整理

    2021-12-14 14:18:49
    今天看到了csdn 的热搜数据,大概分析了下java的一些热门查找,因为csdn的用户大都是一些在校学生,所以热门搜索的问题都是一些基础知识,今天稍微整理下热搜的一些问题,挑一些典型的问题进行解答,希望能对新入手...

     

    今天看到了csdn 的热搜数据,大概分析了下java的一些热门查找,因为csdn的用户大都是一些在校学生,所以热门搜索的问题都是一些基础知识,今天稍微整理下热搜的一些问题,挑一些典型的问题进行解答,希望能对新入手的java新人以启示。OK,废话不多说,走起

    希望各位看官能给点个赞,码字不易,整理不易,你的肯定是我写作的动力

    1、java输入语句

        public static void main(String[] args) {
            //   public final static InputStream in = null;
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()){
                String i = scanner.next();
                System.out.println(i);
            }
        }

    System.in 是从连接控制台的输入流 InputStream

    Scanner 是包装类,可以对InputStream 进行转换,在输入的时候转换为Int ,Boolean 等类型,省去手动转换的麻烦

    2、java开根号

        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNext()){
                int i = scanner.nextInt();
                System.out.println(Math.sqrt(i));
            }
        }
    
    

    这个问题应该是初学者不太清楚Math 下面的都有哪些函数,Math下面包含了我们常用的max,min,ceil ,sqrt ,round等函数,在数学运算的时候如果不太清楚,可以打开api看一下,基本上都能满足你的需求。能用库里的就用库里的,别自己瞎造轮子,你造了别人不喜欢用。

    3、java进制转换

    进制的转换,这种需求太普遍了以至于jdk 直接内置了转换方法,常用的八进制,十六进制,二进制方法直接定义好了,任意进制的也留了进口

    将其他进制的数字转换为十进制 Integer.parseInt("121",3) ,第一个参数是字符串,第二个参数是原来的进制。

        public static void main(String[] args) {
            int n=  16;
            System.out.println(n + "的八进制是:" + Integer.toOctalString(n));
            System.out.println(n + "的二进制是:" + Integer.toBinaryString(n));
            System.out.println(n + "的十六进制是:" + Integer.toHexString(n));
            System.out.println(n + "的3进制是:" + Integer.toString(n, 3));
    ​
    //        radix进制的字符串s转10进制 Integer.parseInt((String) s,(int) radix);
            System.out.println(Integer.parseInt("121",3));
        }

    4、 java 随机整数

    java中产生随机数的方法主要有三种

    第一种:new Random(),Java自带的随机类,可以设置种子进行伪随机,保证每次执行的数据一样

    第二种:Math.random() ,java封装之后的工具函数,最终也是调用的Random类

    第三种:currentTimeMillis(),根据时间的随机性

       public static void main(String[] args) {
            double r1 = Math.random();
            Random random2 = new Random();
            int r2 = random2.nextInt();
            Random random3 = new Random(1000);
            int r3 = random3.nextInt();
            long r4 = System.currentTimeMillis() % 100;
            double r5 = Math.random();
        }

    详细的介绍:战斗要同步,又要有随机,怎么办?大佬告诉我这么做_香菜-CSDN博客

    5、九九乘法表java

    九九乘法表可能是我初学者的课堂作业,所以也是热搜的词,下面我给一个示例代码

        public static void print9x9() {
            for (int i = 1; i <= 9; i++) {
                for (int j = 1; j <= 9; j++) {
                    if (i >= j) {
                        String oneItem = i + "*" + j + "=" + i * j + " ";
                        System.out.print(oneItem);
                    }
                }
                System.out.println();
            }
        }

    注意点:

    循环的上限是9,所以结束的是小于等于好

    换行符要在外层循环打印

    oneItem 代表一个乘法公式

    6、回文数java

    一个正整数,如果交换高低位以后和原数相等,那么称这个数为回文数。比如 121121,23322332都是回文数,13,456713,4567 不是回文数。

    思路:先将数字转为字符串,然后一个字符一个字符进行比较,如果相等则是回文

    public static void main(String[] args) {
            System.out.println(isRevert(110));
        }
        public static boolean isRevert(int num){
            String value=Integer.toString(num);
            char array[]=value.toCharArray();
           for (int i =0;i< value.length()/2;i++){
               if (array[i]!= array[value.length() -i-1]){
                   return false;
               }
           }
           return true;
        }

    注意点:

    第一个位置要和最后一个位置 length-1 进行比较,所以所以是value.length() -i-1

    如果在循环的过程中发现不匹配的字符串,则直接返回false

    7、java二分查找

    二分法检索(binary search)又称折半查找,二分查找的基本思想是设数组中的元素从小到大有序地存放在数组(array)中(注:二分法查找的关键,首先数组元素必须从小到大有序排列),

    (1)首先将给定值 key 与数组中间位置上元素的关键码(key)比较,如果相等,则检索成功;

    (2)否则,若 key 小,则在数组前半部分中继续进行二分法检索;

    (3)若 key 大,则在数组后半部分中继续进行二分法检索。 这样,经过一次比较就缩小一半的检索区间,如此进行下去,直到检索成功或检索失败。 二分法检索是一种效率较高的检索方法。

    
    class BinarySearch{
        /*
            二分法查找
        */
        public static void main(String[] args){
            int[] arr = {1,2,3,4,5,6,7,8};
            int a = 0;
            System.out.println(binarySearch(a,arr));
        }
        // 二分法查找
        static int binarySearch(int a,int[] arr){
            // 最大索引
            int maxIndex = arr.length -1;
            // 最小索引
            int minIndex = 0;
            // 中间索引
            int halfIndex = minIndex+(maxIndex-minIndex)/2;
        
            while (minIndex<=maxIndex){
                // 找到时 
                if (arr[halfIndex]==a){
                    return halfIndex;
                }else if (arr[halfIndex]<a){// 比a小时
                    minIndex = halfIndex + 1;
                }else {// 比a大时
                    maxIndex = halfIndex - 1;
                }
                halfIndex = minIndex+(maxIndex-minIndex)/2;
            }
            return -1;
        }
    }
    ​

    时间复杂度

      1.最坏情况查找最后一个元素(或者第一个元素)Master定理T(n)=T(n/2)+O(1)所以T(n)=O(logn)   2.最好情况查找中间元素O(1)查找的元素即为中间元素(奇数长度数列的正中间,偶数长度数列的中间靠左的元素)

    空间复杂度:

      S(n)=n

    总结:

    大都是一些基础的问题,九层之台起于垒土,基础非常重要,如果不理解的话可以直接记住,或者留言交流,我会及时回复

    展开全文
  • java 拼音搜索功能设计与实现

    千次阅读 2021-12-04 15:36:41
    本篇结合实际案例相信讲解了基于mysql如何实现中文的拼音检索功能

    前言

    在搜索场景中,有下面这种需求,即搜索用户的中文拼音,简拼或全拼,甚至拼音的前几位字母时,能够快速检索出来,如下所示

    在这里插入图片描述

    我们希望得到下面这种效果
    在这里插入图片描述
    这就是一个典型的利用拼音检索功能实现对用户数据搜索的业务,这个看起来简单但实用的功能如何实现呢?

    实现思路分析

    1、借助es

    如果您的用户数据是放在es里面的,那么在存储用户数据的时候,考虑为用户的索引中冗余一个用户中文名称的拼音字段,那么检索的时候,可以将这个拼英字段作为搜索条件进行搜索,es对拼英提供分词的能力

    2、直接在mysql中做

    如果您的用户数据直接存在mysql表中,同样,冗余出一个拼音字段来,查询的时候可以考虑mysql自身的模糊匹配,或者locate函数,将符合条件的数据查询出来

    以上是2种基本实现此功能的思路,但从中,可以捕捉到一个关键的信息就是,需要在入库(es或mysql)的时候,生成一个账户对应的拼音字段,这个转换是关键,这里就需要借助一个外部的组件,本文采用pinyin4j

    功能设计点

    有了上面的基础实现思路,这还不够,还需要考虑的点包括,

    • 该搜索功能支持哪些场景的搜索,如前缀拼音?中间任何一个拼音?全拼?中文名字简拼?
    • 如果中文姓名是多音字,又该如何?

    在调研了一部分真实用户的实际需求场景后发现下面的线索:

    • 使用拼音检索希望缩小检索的范围,用户有时候会忘记目标检索对象的全名,只记得姓氏
    • 更偏向于姓氏前几位,即输入姓氏的某几位,就能给出一批大致符合条件的用户列表
    • 希望一些多音字的名字,也可以支持搜索

    基于上面已知的业务信息,下面就用代码实现这个功能吧

    功能实现步骤

    前置准备

    • 准备一张用户表,注意需要冗余一个拼音字段
    • 搭建一个springboot工程
    CREATE TABLE `db_user` (
      `user_id` varchar(32) NOT NULL COMMENT '用户ID',
      `tenant_id` varchar(32) NOT NULL COMMENT '租户ID',
      `realname` varchar(64) DEFAULT NULL COMMENT '昵称,表示用户真实姓名',
      `account` varchar(64) DEFAULT NULL COMMENT '帐号',
      `email` varchar(64) DEFAULT NULL COMMENT '邮箱',
      `mobile` varchar(32) DEFAULT NULL COMMENT '手机号',
      `passwd` varchar(256) NOT NULL COMMENT '密码',
      `skin` varchar(36) DEFAULT NULL COMMENT '皮肤',
      `key_word` varchar(36) DEFAULT NULL COMMENT '关键词',
      PRIMARY KEY (`user_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    1、引入pinyin4j依赖

    			<dependency>
    				<groupId>com.belerweb</groupId>
    				<artifactId>pinyin4j</artifactId>
    				<version>2.5.0</version>
    			</dependency>
    

    紧接着我们需要考虑的是,在什么样的场景下,需要将这个用户名称的拼音字段存进去呢?很容易想到,新增一个用户,或者修改用户信息的时候,所以需要提供2个基础的接口,接口实现本身并不难,也就是入库的操作

    public String save(DbUser dbUser) {
            DbUser insertUser = new DbUser();
            String userId = UUIDUtils.random();
            BeanUtils.copyProperties(dbUser,insertUser);
            insertUser.setUserId(userId);
            //设置拼音字段
            setKeyWordField(insertUser );
            dbUserMapper.insert(insertUser);
            return "success";
        }
    

    重点考虑的是,保存到key_word 这个字段的拼音存储姓氏,即 realname ——> key_word 的映射 ,那么就需要使用到pinyin4j的提供的相关api做转换操作了,所以接下来,我们需要提供相关的工具类,对生成key_word 的数据做转换

    这个key_word 里面要存储什么样的数据呢?结合上文的业务分析,这里为了后续支持的搜索的方式更丰富,考虑存储的格式如下,以 : 黄小斌 这个名字为例,最后希望转换得到的结果是: huangxiaobin,hxb,即全拼和简拼,为了提升姓氏的检索效率,在将姓氏前缀也提取出来一起拼进去,那么最后的结果是: huangxiaobin,hxb,huang ,中间以逗号分割

    2、转换工具类

    package com.congge.util;
    
    import com.alibaba.dubbo.common.utils.CollectionUtils;
    import lombok.extern.slf4j.Slf4j;
    import net.sourceforge.pinyin4j.PinyinHelper;
    import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
    import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
    import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
    import org.apache.commons.lang3.StringUtils;
    
    import java.io.UnsupportedEncodingException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * 中文名字转拼音工具类
     *
     * @author zhangcy
     * @date 2021-11-04
     */
    @Slf4j
    public class PinYinUtils {
    
        private final static int[] li_SecPosValue = {1601, 1637, 1833, 2078, 2274,
                2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 3858,
                4027, 4086, 4390, 4558, 4684, 4925, 5249, 5590};
    
        private final static String[] lc_FirstLetter = {"a", "b", "c", "d", "e",
                "f", "g", "h", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
                "t", "w", "x", "y", "z"};
    
        /**
         * 取得给定汉字串的首字母串,即声母串
         *
         * @param str 给定汉字串
         * @return 声母串
         */
        public static String getAllFirstLetter(String str) {
            if (str == null || str.trim().length() == 0) {
                return "";
            }
    
            String _str = "";
            for (int i = 0; i < str.length(); i++) {
                _str = _str + getFirstLetter(str.substring(i, i + 1));
            }
    
            return _str;
        }
    
        /**
         * 取得给定汉字的首字母,即声母
         *
         * @param chinese 给定的汉字
         * @return 给定汉字的声母
         */
        public static String getFirstLetter(String chinese) {
            if (chinese == null || chinese.trim().length() == 0) {
                return "";
            }
            chinese = conversionStr(chinese, "GB2312", "ISO8859-1");
    
            if (chinese.length() > 1) // 判断是不是汉字
            {
                int li_SectorCode = (int) chinese.charAt(0); // 汉字区码
                int li_PositionCode = (int) chinese.charAt(1); // 汉字位码
                li_SectorCode = li_SectorCode - 160;
                li_PositionCode = li_PositionCode - 160;
                int li_SecPosCode = li_SectorCode * 100 + li_PositionCode; // 汉字区位码
                if (li_SecPosCode > 1600 && li_SecPosCode < 5590) {
                    for (int i = 0; i < 23; i++) {
                        if (li_SecPosCode >= li_SecPosValue[i]
                                && li_SecPosCode < li_SecPosValue[i + 1]) {
                            chinese = lc_FirstLetter[i];
                            break;
                        }
                    }
                } else // 非汉字字符,如图形符号或ASCII码
                {
                    chinese = conversionStr(chinese, "ISO8859-1", "GB2312");
                    chinese = chinese.substring(0, 1);
                }
            }
    
            return chinese;
        }
    
        /**
         * 字符串编码转换
         *
         * @param str           要转换编码的字符串
         * @param charsetName   原来的编码
         * @param toCharsetName 转换后的编码
         * @return 经过编码转换后的字符串
         */
        public static String conversionStr(String str, String charsetName, String toCharsetName) {
            try {
                str = new String(str.getBytes(charsetName), toCharsetName);
            } catch (UnsupportedEncodingException ex) {
                System.out.println("字符串编码转换异常:" + ex.getMessage());
            }
            return str;
        }
    
        /**
         * 首字母大写
         *
         * @param name 参数中文字符串
         * @return result
         * @throws {@link BadHanyuPinyinOutputFormatCombination}
         */
        public static String getChinesePinyinFromName(String name) {
            String result = null;
            try {
                HanyuPinyinOutputFormat pyFormat = new HanyuPinyinOutputFormat();
                pyFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
                pyFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
                pyFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
                result = PinyinHelper.toHanyuPinyinString(name, pyFormat, "");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
        public static boolean isChineseName(String name) {
            boolean result = true;
            if (StringUtils.isNotEmpty(name)) {
                String[] strChars = name.split("");
                for (String singleStr : strChars) {
                    if (!isContainChinese(singleStr)) {
                        result = false;
                        break;
                    }
                }
            }
            return result;
        }
    
        public static boolean isContainChinese(String str) {
            Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
            Matcher m = p.matcher(str);
            if (m.find()) {
                return true;
            }
            return false;
        }
    
        public static String getChineseFirstPingYingName(String str) {
            String[] split = str.split("");
            return PinYinUtils.getChinesePinyinFromName(split[0]);
        }
    
        public static String convert(String chineseName) {
            String nameVar1 = getChinesePinyinFromName(chineseName);
            String nameVar2 = getAllFirstLetter(chineseName);
            String nameVar3 = getChineseFirstPingYingName(chineseName);
            String result = nameVar1 + "," + nameVar2 + "," + nameVar3;
            return result;
        }
    
        public static boolean isMixedStr(String realname) {
            String[] splitStr = realname.split("");
            List<String> allStrs = Arrays.asList(splitStr);
            List<String> allLastStr = new ArrayList<>();
            boolean hasChinese = false;
            for (String single : splitStr) {
                if (isChineseName(single)) {
                    hasChinese = true;
                } else {
                    allLastStr.add(single);
                }
            }
            if (hasChinese) {
                if (CollectionUtils.isNotEmpty(allStrs) && CollectionUtils.isNotEmpty(allLastStr) && allLastStr.size() < allStrs.size()) {
                    hasChinese = true;
                }
            }
            return hasChinese;
        }
    
    
        public static void main(String[] args) {
            PinYinUtils pinYinUtils = new PinYinUtils();
            String chineseName = "胡";
            String nameVar1 = pinYinUtils.getChinesePinyinFromName(chineseName);
            String nameVar2 = pinYinUtils.getAllFirstLetter(chineseName);
            String nameVar3 = pinYinUtils.getChineseFirstPingYingName(chineseName);
            System.out.println(nameVar1);
            System.out.println(nameVar2);
            System.out.println(nameVar3);
        }
    
        private static PinYinMultiCharactersUtils pinYinMultiCharactersUtils = new PinYinMultiCharactersUtils();
    
        /**
         * 如果是中文何字符串等混合过来的,只需原样解析,比如:111董aaa飞飞333 ,解析为:111dongaaafeifei333
         *
         * @param realname
         * @return
         */
        public String getMixPinyinStr(String realname) {
            if (StringUtils.isEmpty(realname)) {
                return null;
            }
            String[] splitStr = realname.split("");
            StringBuilder stringBuilder = new StringBuilder();
            int firstIndex = 0;
            for (String single : splitStr) {
                if (isChineseName(single)) {
                    //只有第一个中文多音字做解析
                    if (firstIndex == 0 && pinYinMultiCharactersUtils.isMultiChineseWord(single)) {
                        String chinesePinyinFromName = pinYinMultiCharactersUtils.getMultiCharactersPinYin(single);
                        stringBuilder.append(chinesePinyinFromName);
                        continue;
                    }
                    String chinesePinyinFromName = getChinesePinyinFromName(single);
                    stringBuilder.append(chinesePinyinFromName);
                    firstIndex++;
                } else {
                    stringBuilder.append(single);
                }
            }
            return stringBuilder.toString();
        }
    }
    
    

    关于工具类中的一些方法,通过注释想必大家也能看懂,下面要重点说下,如何使用这个工具类呢?还是回到上面那个saveUser的方法中,如何设置这个keyWord的属性值上面来,请看下面这个方法,我们以这个方法为例做深入的剖析

    private void setKeyWordField(DbUser userRequest) {
            if(StringUtils.isEmpty(userRequest.getRealname())){
                return;
            }
            /**
             * 1、pinYinUtils.isChineseName 判断传入过来的名称是否是中文呢?如果全部是中文的话做基础的解析
             * 2、pinYinUtils.convert 做拼音转换
             * 3、pinYinMultiCharactersUtils.getMultiCharactersPinYin 如果名字中的姓氏是多音字时,还需要做一下特别处理
             * 4、如果用户名中不全是中文,比如: 周小斌_bank_1 ,类似这样的,或者 : bank_1_周小斌 ,只转换其中的中文,不改变整个字符串的顺序
             */
    
            if (pinYinUtils.isChineseName(userRequest.getRealname())) {
                String originalConvert = pinYinUtils.convert(userRequest.getRealname());
                String multiConvertResult =  pinYinMultiCharactersUtils.getMultiCharactersPinYin(userRequest.getRealname());
                if(StringUtils.isNotEmpty(multiConvertResult)){
                    userRequest.setKeyWord(originalConvert.concat(",").concat(multiConvertResult));
                    return;
                }
                userRequest.setKeyWord(originalConvert );
            }else {
                //如果不全部是中文,即除了中文之外,还有其他字符混在一起的话,这种才做解析
                if(pinYinUtils.isMixedStr(userRequest.getRealname())){
                    userRequest.setKeyWord(pinYinUtils.getMixPinyinStr(userRequest.getRealname()));
                }
            }
        }
    

    参考其中的4条解释说明,

    1. pinYinUtils.isChineseName 判断传入过来的名称是否是中文呢?如果全部是中文的话做基础的解析
    2. pinYinUtils.convert 做拼音转换
    3. pinYinMultiCharactersUtils.getMultiCharactersPinYin 如果名字中的姓氏是多音字时,还需要做一下特别处理
    4. 如果用户名中不全是中文,比如: 周小斌_bank_1 ,类似这样的,或者 : bank_1_周小斌 ,只转换其中的中文,不改变整个字符串的顺序

    该方法即把上面拼音转换工具类中的所有方法全部调起来使用了,工具类方法本身并不太难,但是需要结合自身的业务场景合理使用

    关于多音字处理

    在上午中,我们还提到,在实际的用户名称中,存在那些多音字的场景,比如: 单,正常解析出来就是 “dan” ,很明显这是不符合要求的,姓氏中应该解析为 “shan” (忽略 chan) ,或 “解” ,就应该解析为 “xie” ,这样分析之后发现,解析 “解小龙” 这个名字时,如果按照上面的工具类,解析出来的应该是 : jiexiaobin,jxb,如果再经过多音字的解析,还应该解析出 “xiexiaobin” 这个拼音,那么完整的冗余 keyWord字段值为:jiexiaobin,jxb,jie,xiexiaobin(考虑到使用系统的用户并不知道哪些是多音字)

    解析多音字比较常用的做法是,维护一个常用的多音字的字典对照表,这个和 es中维护的停用词字典很像,这里直接列出提供参考,后续可以手动添加

    在这里插入图片描述

    a#阿
    ao#拗口/违拗/拗断/执拗/拗口/拗口风/拗口令/拗曲/拗性/拗折/警拗
    ai#艾
    bang#膀/磅/蚌
    ba#扒
    bai#叔伯/百/柏杨/㧳/梵呗/呗佛/呗音/呗唱/呗偈/呗声/呗赞/赞呗
    bao#剥皮/薄/暴/堡/曝
    bei#呗
    beng#蚌埠
    bi#复辟/臂/秘鲁/泌阳
    bing#屏息/屏弃/屏气/屏除/屏声
    bian#扁/便/便宜坊
    bo#薄荷/单薄/伯/泊/波/柏/萝卜/孛
    bu#卜/柨
    can#参
    cang#藏/欌
    cen#参差
    ceng#曾/噌
    cha#差/刹那/宝刹/一刹/查/碴/喳喳/喀喳
    chai#公差/差役/专差/官差/听差/美差/办差/差事/差使/肥差/当差/钦差/苦差/出差
    chan#颤/单于/禅
    chang#长/厂
    chao#朝/嘲/焯
    che#工尺/车
    chen#称职/匀称/称心/相称/对称
    cheng#称/乘/澄/噌吰/橙 秤/盛满/盛器/盛饭
    chu#畜
    chui#椎心
    chuai#揣
    chuan#传
    chi#匙/尺/吃
    chong#重庆/重重/虫
    chou#臭/帱
    chuang#经幢
    chuo#绰
    ci#参差/鳞差/伺候/龟兹
    cuan#攒聚/攒动/攒集/攒宫/攒所
    cuo#撮儿/撮要/撮合
    da#大/嗒
    dao#叨/帱载/帱察
    dai#大夫
    dan#单/弹/掸/澹
    dang#铛
    de#的/得
    di#堤/底/怎的/有的/目的/标的/打的/的确/有的放/的卢/矢之的/言中的/语中的/的士/地/提防/快的/美的
    diao#蓝调/调调/音调/论调/格调/调令/低调/笔调/基调/强调/声调/滥调/老调/色调/单调/腔调/跑调/曲调/步调/语调/主调/情调
    ding#丁
    du#读/都/度
    dou#全都/句读
    duo#舵/测度/忖度/揣度/猜度
    dun#粮囤/盾/顿/沌/敦
    e#阿谀/阿胶/阿弥/恶/擜
    er#儿
    fan#番
    feng#冯
    fei#婔
    fo#佛
    fu#仿佛/果脯/罘/莩
    fou#否
    fiao#覅
    ga#咖喱/伽马/嘎/戛纳
    gai#盖
    gao#告
    gang#扛鼎
    ge#革/蛤蚧/文蛤/蛤蜊/咯
    gei#给
    geng#脖颈
    gong#女红/共
    gu#谷/中鹄/鼓
    gui#龟/柜/硅/倭傀/傀异/傀然/傀垒/傀怪/傀卓/傀奇/傀伟/傀民/傀俄/琦傀/奇傀
    gua#呱
    guan#纶巾/东莞
    guang#广
    ha#蛤/哈/虾蟆
    hai#还/嗨/咳声/咳笑
    hao#貉子/貉绒
    hang#夯/总行/分行/支行/行业/排行/行情/央行/商行/外行/银行/中行/交行/招行/农行/工行/建行/商行/酒行/麻行/琴行/行业/同行/行列/行货/行会/行家/巷道/引吭/扼吭/批吭/搤吭/高吭/喉吭/咔吭/絶吭/吭嗌/吭咽/吭首
    he#和/合/核/鶴/猲
    heng#道行/涥
    hu#鹄/水浒/嗀/唬
    hua#滑/呚/椛
    huan#归还/放还/奉还/圜
    hui#会/浍河/媈/灳/哕/瑗珲
    hong#红/虹
    huo#软和/热和/暖和
    hun#尡/珲
    ji#病革/给养/自给/给水/薪给/给予/供给/稽/缉/藉/奇数/亟/诘屈/荠菜/愱
    jia#雪茄/伽/家/价/贾/戛
    jian#见/浅浅
    jiang#降
    jiao#嚼舌/嚼字/嚼蜡/角/剿/饺/脚/蕉/矫/睡觉/侥/校对/校验/校正/校准/审校/校场/校核/校勘/校订/校阅/校样
    jie#慰藉/蕴藉/诘/媘/煯
    jin#矜/劲/禁
    jing#颈/景/强劲/劲风/劲旅/劲敌/劲射/苍劲/遒劲/劲草
    jiong#炅
    ju#咀/居/桔/句/婮
    jun#均
    juan#棚圈/圈养/猪圈/羊圈
    jue#主角/角色/旦角/女角/丑角/角力/名角/配角/嚼/觉/䏐
    jun#龟裂/俊
    ka#咖/卡/喀
    kai#楷
    kang#扛
    ke#咳/壳
    keng#吭
    kuai#会计/财会/浍
    kui#傀
    kuo#括
    la#癞痢/腊/蜡
    lai#癞疮/癞子/癞蛤/癞皮
    lao#积潦/络子/落枕/落价/粩/姥
    le#乐/勒/了
    lei#勒紧
    lo#然咯
    lou#佝偻/泄露/露面/露脸/露骨/露底/露馅/露一手/露相/露马脚/露怯
    long#里弄/弄堂/泷
    li#跞/礼/櫔/栃
    liao#了解/了结/明了/了得/末了/未了/了如/潦/撩
    liang#靓/俩
    lie#挘
    lin#崊
    ling#霗/令
    liu#六/遛
    lu#碌/陆/露
    luo#络/落/漯/囖/洜/泺
    lv#率/绿
    lve#鋢/稤
    lun#纶
    ma#嫲/抹布/抹脸/抹桌子/摩挲
    mai#埋
    man#埋怨/蔓
    mai#脉
    mang#氓/芒
    mao#冒
    me#嚒
    men#椚
    meng#群氓/盟/癦
    mei#没/旀
    mo#淹没/没收/出没/沉没/没落/吞没/覆没/没入/埋没/鬼没/隐没/湮没/辱没/脉脉/模/摩/抹
    mou#绸缪/牟
    mi#秘/泌尿/分泌/谜/檷枸
    mian#渑
    ming#掵
    miu#谬/谬论/纰缪
    mu#大模/字模/模板/模样/模具/装模/模子/牟尼/子牟/夷牟/悬牟/相牟/头牟/宾牟/曹牟/岑牟/兜牟/卢牟/弥牟/牟食/牟槊/牟衫/牟光/牟牟/牟甲
    na#哪/娜/那
    nao#臑
    nan#南
    ne#哪吒/呢
    nei#氞
    neus#莻
    nong#弄/燶
    ni#毛呢/花呢/呢绒/线呢/呢料/呢子/呢喃/溺/檷
    niao#尿/鸟/便溺
    nian#粘膜/粘度/粘土/粘合剂/粘液/粘稠/粘合/粘着/粘结/粘性/粘附/不粘锅/粘糊/粘虫/粘聚/粘滞/焾/哖
    niang#酿
    nin#脌
    ning#倿/拧
    niu#拗/汼
    nu#努
    nuo#婀娜/袅娜/喏
    nv#女
    nve#疟/硸
    o#喔/筽
    ou#膒
    pa#扒手/扒窃/扒外/扒分/扒糕/扒灰/扒犁/扒龙/扒搂/扒山虎/扒艇
    pai#派/迫击/迫击炮
    pao#刨/炮/萢
    pan#番禺
    pang#胖/膀/磅
    pei#蓜
    pi#辟/否极/臧否/龙陂/芘
    pian#扁舟/便宜/魸
    piao#朴姓/饿莩/饥莩/葭莩
    pin#穦
    ping#屏/苹/冯河
    po#湖泊/血泊 /迫/朴刀/坡/陂
    pu#一曝十寒/里堡/十里堡/脯/朴/曝晒/瀑/埔
    qi#期/其/泣/祇
    qiu#龟兹/湭
    qi#稽首/缉鞋/栖/奇/漆/齐
    qia#卡脖/卡子/关卡/卡壳/哨卡/边卡/发卡/峠
    qiao#雀盲/雀子/地壳/甲壳/躯壳
    qian#纤/乾/浅
    qiang#强/㛨/㩖/䅚/䵁
    qie#茄/趔趄/聺/籡
    qin#亲/沁
    qing#干亲/亲家
    qiong#熍
    qu#区/趣/爠
    quan#圈/券
    que#雀/炔
    re#声喏/唱喏
    rong#嬫
    ruo#若/嵶
    saeng#栍
    sang#槡
    sai#塞/嘥
    sao#螦
    se#堵塞/搪塞/茅塞/闭塞/鼻塞/梗塞/阻塞/淤塞/拥塞/哽塞/色
    sha#莎/刹车/急刹/厦/杉木/杉篙
    shai#色子
    shao#勺/红苕
    shan#姓单/单/单县/杉/敾/禅让/受禅/禅变/禅代/禅诰
    shang#衣裳
    she#拾级/折本/射/蛇
    shen#沙参/野参/参王/人参/红参/丹参/山参/海参/鹿参/什么/身/沈/桑椹/食椹/烂椹/木椹
    sheng#野乘/千乘/史乘/省/晟/盛/陹/渑水
    shi#钥匙/什/识/似的/食/石/氏/拾/适/瑡
    shiwa#瓧
    shuai#表率/率性/率直/率真/粗率/率领/轻率/直率/草率/大率/坦率/衰
    shuang#泷水/鏯
    shu#属/数/术/熟
    shui#游说
    shuo#数见/说
    si#伺/似/思
    sou#蓃/摗
    su#宿/鯂
    sui#尿泡
    ta#拓片/拓印/拓本/拓墨/拓写/拓手/拓工/碑拓/疲沓/拖沓/杂沓/沓/塔/鸿塔
    tang#汤/镗
    tao#陶
    tan#反弹/弹性/弹簧/弹力/弹奏/弹跳/弹指/弹劾/弹唱/弹射/弹性体/吹弹/评弹/乱弹琴/弹压/弹指/弹簧/弹冠/弹雀/弹雀/弹丝/弹丸/澹台
    te#脦
    teng#虅
    ti#提/体
    tiao#调/苕
    ting#町/听
    tong#通
    tu#迌
    tuan#湪
    tui#褪
    tuo#拓/袥
    tun#囤/屯
    wei#尾/蔚/圩堤/圩垸/圩田/圩子/赶圩/歌圩
    weng#攚
    wu#无/可恶/交恶/好恶/厌恶/憎恶/嫌恶/痛恶/深恶/兀
    wan#藤蔓/枝蔓/根蔓/蔓草/瓜蔓/蔓儿/莞/万/百万/皖
    wang#亡
    wai#崴
    xia#虾/吓/夏/厦门/厦大/唬杀
    xi#栖/系/蹊/洗/溪/戏/焁/铣/褶衣/褶裤
    xiao#校/切削/削面/刀削/刮削
    xian#纤细/光纤/纤巧/纤柔/纤小/纤维/纤瘦/纤纤/化纤/纤秀/棉纤/纤尘/铣铁/金铣
    xiang#投降/巷
    xie#解/解数/出血/采血/换血/血糊/尿血/淤血/放血/血晕/血淋/便血/吐血/咯血/叶韵/蝎/蝎子/邪/猲猲
    xin#嬜/邤
    xiu#铜臭/乳臭/成宿/星宿/璓
    xin#馨/信/鸿信
    xing#深省/省视/内省/不省人事/省悟/省察/行/荥
    xiong#匂
    xu#牧畜/畜产/畜牧/畜养/并畜/畜锐/吁/圩/浒
    xuan#箮
    xue#削/血/樰
    xun#荨/寻
    ya#琊
    yao#钥/耀/曜/佋侥/侥觎/侥僺/侥利/侥傒/侥觊/侥会/侥滥/侥望/侥求/侥竞/侥薄/侥躐/侥取/侥奇/侥忝/侥速/侥冀/侥冒/疟子
    yan#咽/殷红/朱殷/腌/烟/曕
    ye#液/抽咽/哽咽/咽炎/呜咽/幽咽/悲咽/叶/葉/璍/潱/拽步/拽扶/拽扎
    yi#自艾/遗/屹/嬄/噫
    yin#殷/栶
    ying#荥经/緓/灜
    yo#杭育
    yong#涌/硧
    you#牗
    yu#余/呼吁/吁请/吁求/育/熨帖/熨烫/於
    yuan#员/茒/圜丘
    yun#熨
    yue#约/乐音/器乐/乐律/乐章/音乐/乐理/民乐/乐队/声乐/奏乐/弦乐/乐坛/管乐/配乐/乐曲/乐谱/锁钥/密钥/乐团/乐器/嬳/咽哕/唾哕/发哕/干哕/哕吐/哕饭/哕呕/哕息/哕厥/哕噫/哕逆/哕咽/哕骂/哕心/哕喈/口哕/呕哕
    za#绑扎/结扎/包扎/捆扎/咱家
    zan#攒/咱
    zang#宝藏/藏历/藏文/藏语/藏青/藏族/藏医/藏药/藏蓝/西藏
    zai#牛仔/龟仔/龙仔/鼻仔/羊仔/仔仔/麻仔/麵包仔/麦旺仔/鸿仔/煲仔/福仔/畠
    zao#栆
    ze#择
    zeng#曾国藩/曾孙/曾祖父/曾祖/曾祖母/曾孙女/曾巩/囎/缯
    zong#综/繌
    zha#扎/柞狭/柞薪/柞子/柞鄂/柞叶/柞撒/槱柞/一柞/五柞宫/五柞/雠柞/芟柞/蜡祭/喳
    zhai#宅/夈/择席/择菜
    zhan#粘
    zhang#列车长/行长/村长/镇长/乡长/区长/县长/市长/省长/会长/班长/排长/连长/营长/团长/旅长/师长/军长/委员长/局长/厅长/所长/部长/组长/生长/长大/长高/长个/
    zhao#朝朝/明朝/朝晖/朝夕/朝思/今朝/朝气/朝三/朝秦/朝霞/鹰爪/龙爪/魔爪/爪牙/着急/着迷/着火/怎么着/正着/着凉/一着/犯不着/着数/这么着/犯得着/着慌/着忙/数得着/龙爪槐/嘲哳/嘲惹
    zhe#折/着/褶
    zhen#殝/椹
    zhi#标识/吱/殖/枝/方祇/后祇/皇祇/黄祇/皇地祇/金祇/祇树/月氏
    zhong#重/种
    zhou#粥
    zhu#属意/著/駯
    zhua#爪子
    zhuai#拽
    zhuan#芈月传/外传/传记/自传/正传/小传/评传/传略/别传
    zhui#椎/隹
    zhuo#执著/着装/着落/着意/着力/附着/着笔/胶着/着实/衣着/着眼/着想/着重/穿着/执着/着墨/着实/沉着/着陆/着想/着色/焯见/焯烁/辉焯
    zhuang#幢房/一幢/幢楼/庒
    zi#仔/兹
    zu#足
    zuo#柞/穝
    
    

    最后再提供一个解析多音字的工具类

    package com.congge.utils.pyin;
    
    import net.sourceforge.pinyin4j.PinyinHelper;
    import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
    import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
    import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
    import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 处理多音字的扩展工具类
     *
     * @author zhangcy
     * @date 2021-12-02
     */
    public class PinYinMultiCharactersUtils {
    
        private static final Logger logger = LoggerFactory.getLogger(PinYinMultiCharactersUtils.class);
    
        private static Map<String, List<String>> pinyinMap = new HashMap<>();
    
        private static Map<String, List<String>> otherSpecialWord = new HashMap<>();
    
        static {
            //这里如果apollo上面没有配置任何的值,默认初始化一些常用的
            otherSpecialWord.put("解", Arrays.asList("xie"));
            otherSpecialWord.put("查", Arrays.asList("zha"));
            otherSpecialWord.put("单", Arrays.asList("shan"));
            otherSpecialWord.put("朴", Arrays.asList("piao"));
            otherSpecialWord.put("区", Arrays.asList("ou"));
            otherSpecialWord.put("仇", Arrays.asList("qiu"));
            otherSpecialWord.put("阚", Arrays.asList("kan"));
            otherSpecialWord.put("种", Arrays.asList("chong"));
            otherSpecialWord.put("盖", Arrays.asList("ge"));
            otherSpecialWord.put("繁", Arrays.asList("po"));
    
        }
    
        public static String toPinyin(String str) {
            try {
                initPinyin("/duoyinzi.dic.txt");
                String py = convertChineseToPinyin(str);
                System.out.println(str + " = " + py);
                return py;
            } catch (Exception e) {
                logger.error("convert pinyin error,e : {}", e);
                return null;
            }
        }
    
        /**
         * 通过拆分名字的方式 获取多音字的名字的完整拼音
         *
         * @param chinese
         * @return
         */
        public static String getMultiCharactersPinYin(String chinese) {
            if (StringUtils.isEmpty(chinese)) {
                return null;
            }
            String result = null;
            if (chinese.length() >= 2) {
                String[] nameElements = chinese.split("");
                String firstName = nameElements[0];
                if (!isMultiChineseWord(firstName)) {
                    return null;
                }
                String secondName = null;
                StringBuilder sb = new StringBuilder();
                for (String str : nameElements) {
                    if (!str.equals(firstName)) {
                        sb.append(str);
                    }
                }
                secondName = sb.toString();
                //获取多音字的拼音
                String partOne = PinYinMultiCharactersUtils.toPinyin(firstName);
                String partTwo = PinYinMultiCharactersUtils.toPinyin(secondName);
                result = partOne.concat(partTwo).toLowerCase();
            } else {
                result = PinYinMultiCharactersUtils.toPinyin(chinese);
            }
            return result;
        }
    
        /**
         * 将某个字符串的首字母大写
         *
         * @param str
         * @return
         */
        public static String convertInitialToUpperCase(String str) {
            if (str == null) {
                return null;
            }
            StringBuffer sb = new StringBuffer();
            char[] arr = str.toCharArray();
            for (int i = 0; i < arr.length; i++) {
                char ch = arr[i];
                if (i == 0) {
                    sb.append(String.valueOf(ch).toUpperCase());
                } else {
                    sb.append(ch);
                }
            }
    
            return sb.toString();
        }
    
        /**
         * 判断当前中文字是否多音字
         *
         * @param chinese
         * @return
         */
        public static boolean isMultiChineseWord(String chinese) {
            HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
            defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            char[] arr = chinese.toCharArray();
            for (int i = 0; i < arr.length; i++) {
                char ch = arr[i];
                if (ch > 128) {
                    // 非ASCII码,取得当前汉字的所有全拼
                    try {
                        String[] results = PinyinHelper.toHanyuPinyinStringArray(ch, defaultFormat);
                        if (results == null) {
                            //非中文
                            return false;
                        } else {
                            int len = results.length;
                            if (len == 1) {
                                // 不是多音字
                                return false;
                            } else if (results[0].equals(results[1])) {
                                //非多音字 有多个音,默认取第一个
                                if (otherSpecialWord.containsKey(chinese)) {
                                    return true;
                                }
                                return false;
                            } else {
                                // 多音字
                                return true;
                            }
                        }
                    } catch (BadHanyuPinyinOutputFormatCombination e) {
                        logger.error("BadHanyuPinyinOutputFormatCombination ,e :{}", e);
                    }
                }
            }
            return false;
        }
    
        /**
         * 汉字转拼音 最大匹配优先
         *
         * @param chinese
         * @return
         */
        private static String convertChineseToPinyin(String chinese) {
            StringBuffer pinyin = new StringBuffer();
            HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
            defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
            defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
            char[] arr = chinese.toCharArray();
            for (int i = 0; i < arr.length; i++) {
                char ch = arr[i];
                if (ch > 128) {
                    // 非ASCII码 取得当前汉字的所有全拼
                    try {
                        String[] results = PinyinHelper.toHanyuPinyinStringArray(ch, defaultFormat);
                        if (results == null) {  //非中文
                            return "";
                        } else {
                            int len = results.length;
                            if (len == 1) {
                                // 不是多音字
                                String py = results[0];
                                if (py.contains("u:")) {  //过滤 u:
                                    py = py.replace("u:", "v");
                                    logger.info("filter u: {}", py);
                                }
                                pinyin.append(convertInitialToUpperCase(py));
                            } else if (results[0].equals(results[1])) {
                                //非多音字 有多个音,取第一个
                                if (otherSpecialWord.containsKey(chinese)) {
                                    return otherSpecialWord.get(chinese).get(0);
                                }
                                pinyin.append(convertInitialToUpperCase(results[0]));
                            } else {
                                logger.info("多音字:{}", ch);
                                if (otherSpecialWord.containsKey(chinese)) {
                                    pinyin.append(otherSpecialWord.get(chinese).get(0));
                                    continue;
                                }
                                int length = chinese.length();
                                boolean flag = false;
                                String s = null;
                                List<String> keyList = null;
                                for (int x = 0; x < len; x++) {
                                    String py = results[x];
                                    if (py.contains("u:")) {
                                        py = py.replace("u:", "v");
                                        logger.info("filter u :{}", py);
                                    }
                                    keyList = pinyinMap.get(py);
                                    if (i + 3 <= length) {
                                        //后向匹配2个汉字  大西洋
                                        s = chinese.substring(i, i + 3);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));
                                            flag = true;
                                            break;
                                        }
                                    }
                                    if (i + 2 <= length) {
                                        //后向匹配 1个汉字  大西
                                        s = chinese.substring(i, i + 2);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));
                                            flag = true;
                                            break;
                                        }
                                    }
                                    if ((i - 2 >= 0) && (i + 1 <= length)) {
                                        // 前向匹配2个汉字 龙固大
                                        s = chinese.substring(i - 2, i + 1);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));
                                            flag = true;
                                            break;
                                        }
                                    }
                                    if ((i - 1 >= 0) && (i + 1 <= length)) {
                                        // 前向匹配1个汉字   固大
                                        s = chinese.substring(i - 1, i + 1);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));
                                            flag = true;
                                            break;
                                        }
                                    }
                                    if ((i - 1 >= 0) && (i + 2 <= length)) {
                                        //前向1个,后向1个  固大西
                                        s = chinese.substring(i - 1, i + 2);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));
                                            flag = true;
                                            break;
                                        }
                                    }
                                }
                                if (!flag) {
                                    //都没有找到,匹配默认的 读音  大
                                    s = String.valueOf(ch);
                                    for (int x = 0; x < len; x++) {
                                        String py = results[x];
                                        if (py.contains("u:")) {  //过滤 u:
                                            py = py.replace("u:", "v");
                                        }
                                        keyList = pinyinMap.get(py);
                                        if (keyList != null && (keyList.contains(s))) {
                                            pinyin.append(convertInitialToUpperCase(py));//拼音首字母 大写
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    } catch (BadHanyuPinyinOutputFormatCombination e) {
                        logger.error("BadHanyuPinyinOutputFormatCombination :{}", e);
                    }
                } else {
                    pinyin.append(arr[i]);
                }
            }
            return pinyin.toString();
        }
    
        /**
         * 初始化 所有的多音字词组
         *
         * @param fileName
         */
        public static void initPinyin(String fileName) {
            if (pinyinMap != null && !pinyinMap.isEmpty()) {
                return;
            }
            // 读取多音字的全部拼音表;
            InputStream file = PinyinHelper.class.getResourceAsStream(fileName);
            BufferedReader br = new BufferedReader(new InputStreamReader(file));
            String s = null;
            try {
                while ((s = br.readLine()) != null) {
                    if (s != null) {
                        String[] arr = s.split("#");
                        String pinyin = arr[0];
                        String chinese = arr[1];
                        if (chinese != null) {
                            String[] strs = chinese.split(" ");
                            List<String> list = Arrays.asList(strs);
                            pinyinMap.put(pinyin, list);
                        }
                    }
                }
            } catch (IOException e) {
                logger.error("IOException,{}", e);
            } finally {
                try {
                    br.close();
                } catch (IOException e) {
                    logger.error("IOException,{}", e);
                }
            }
        }
    
    }
    
    
    

    写一个方法测试下,效果如下:
    在这里插入图片描述

    最后,提供一个新增用户的接口吧,测试一下接口的功能是否能满足要求

        @PostMapping("/save")
        public String save(@RequestBody DbUser dbUser){
            return dbUserService.save(dbUser);
        }
    

    测试场景1:正常的中文名称

    在这里插入图片描述

    在这里插入图片描述
    测试场景2:多音字的中文名称
    在这里插入图片描述
    测试场景3:中文名字中插入英文等其他字符
    在这里插入图片描述

    在这里插入图片描述

    按照拼音检索用户信息

    查询的时候,就可以了利用keyWord这个字段进行搜索了,代码就不再写了,关键的sql语句可以参考如下:

    select * from db_user where key_word like '%xie%';
    
    select * from db_user where key_word like 'xie%';
    
    select * from db_user where LOCATE('xie',`key_word`);
    

    在这里插入图片描述

    本篇到此结束,最后感谢观看!

    展开全文
  • 微博热搜数据

    千次阅读 2021-03-12 22:56:48
    爬虫名称:爬取微博热搜2.爬虫爬取的内容:爬取微博热搜数据。 数据特征分析:各数据分布紧密联系。3.网络爬虫设计方案概述:实现思路:通过访问网页源代码使用xpath正则表达爬取数据,对数据进行保存数据,再对数据...

    ------主题式网络主题式网络爬虫设计方案------

    1.爬虫名称:爬取微博热搜

    2.爬虫爬取的内容:爬取微博热搜数据。 数据特征分析:各数据分布紧密联系。

    3.网络爬虫设计方案概述:

    实现思路:通过访问网页源代码使用xpath正则表达爬取数据,对数据进行保存数据,再对数据进行清洗和处理,数据分析与可视化处理。

    技术难点:在编程的过程中,若中间部分出现错误,可能导致整个代码需要重新修改。数据实时更新,会导致部分上传的图形不一致。

    ------主题页面的结构特征分析------

    1.主题页面的结构和特征分析:爬取数据都分布在标签'div.cc-cd-cb nano has-scrollbar'里面,标题标签为'span.t',热度标签为'span.e'。

    2.Htmls页面解析:

    283eaacc6cdf3bfaa6a6966b3a6e107b.png

    44b2f9954334d8342ad73d259e063475.png

    3.节点(标签)查找方法与遍历方法:通过xpath遍历标签。利用xpath正则表达查找。

    ------网络爬虫程序设计------

    importrequestsfrom lxml importetreeimportpandas as pdimportnumpy as npimportmatplotlib.pyplot as pltimportmatplotlibfrom scipy.optimize importleastsqimportscipy.stats as stsimportseaborn as sns

    url= "https://tophub.today/"headers= {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'}

    html= requests.get(url,headers = headers)

    html= html.content.decode('utf-8')

    html = etree.HTML(html)

    div= html.xpath("//div[@id='node-1']/div")for a in div:

    titles = a.xpath(".//span[@class='t']/text()")

    numbers = a.xpath(".//span[@class='e']/text()")

    b= []

    for i in range(25):

    b.append([i+1,titles[i],numbers[i][:-1]])

    file = pd.DataFrame(b,columns = ['排名','今日热搜','热度(单位为万)'])print(file)

    file.to_csv('微博热搜榜热度数据.csv')

    328d1ee04adf6f7f6a604f1b4dcb93b5.png

    eb8cfc5844b5f4a5d49f30c445efcd76.png

    2.对数据进行清洗和处理:

    df = pd.DataFrame(pd.read_csv('微博热搜榜热度数据.csv'))

    df.head()

    334738ce769183d70445e19e6532c4b2.png

    df.drop('今日热搜', axis=1, inplace=True)

    df.head()

    c4d16c917e8ee9a2d05b6b5b5919ab5d.png

    df.isnull().sum()

    b787957365936ec6dd117e355dbabfcb.png

    df[df.isnull().values==True]

    b9b2d0db0f5030a18185f9e79d1ac84a.png

    df.describe()

    25a2eef665a977676fa6383757886d57.png

    3.数据分析与可视化:

    df.corr()

    c4217506a895b31dbdd11db6efa65204.png

    sns.lmplot(x='排名',y='热度(单位为万)',data=df)

    e1199a5b344e0bfb02910e9409dcc7de.png

    defone():

    file_path= "'微博热搜榜热度数据.csv'"x= df['排名']

    y= df['热度(单位为万)']

    plt.xlabel('排名')

    plt.ylabel('热度(单位为万)')

    plt.bar(x,y)

    plt.title("绘制排名与热度条形图")

    plt.show()

    one()

    676702e16446f698b927089387902bd9.png

    deftwo():

    x= df['排名']

    y= df['热度(单位为万)']

    plt.xlabel('排名')

    plt.ylabel('热度(单位为万)')

    plt.plot(x,y)

    plt.scatter(x,y)

    plt.title("绘制排名与热度折线图")

    plt.show()

    two()

    5859440e86a8f8409955d9809493913e.png

    defthree():

    x= df['排名']

    y= df['热度(单位为万)']

    plt.xlabel('排名')

    plt.ylabel('热度(单位为万)')

    plt.scatter(x,y,color="red",label=u"热度分布数据",linewidth=2)

    plt.title("绘制排名与热度散点图")

    plt.legend()

    plt.show()

    three()

    7005dfcd88f8548bf767364c703c8b5f.png

    4.根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程:

    一元一次回归方程:

    defmain():

    colnames= ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)'

    f = pd.read_csv('微博热搜榜热度数据.csv',skiprows=1,names=colnames)

    X=f.排名

    Y=f.numberdeffunc(p,x):

    k,b=preturn k*x+bdeferror_func(p,x,y):return func(p,x)-y

    p0= [1,20]

    Para= leastsq(error_func,p0,args =(X,Y))

    k,b=Para[0]print("k=",k,"b=",b)

    plt.figure(figsize=(8,6))

    plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2)

    x=np.linspace(0,30,25)

    y=k*x+b

    plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2)

    plt.title("微博今日热搜排名和热度关系图")

    plt.xlabel('排名')

    plt.ylabel('热度(单位为万)')

    plt.legend()

    plt.show()

    main()

    41a529cf3ee2911eafaad2aa1173a0c3.png

    一元二次回归方程:

    deffour():

    colnames= ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)'

    f = pd.read_csv('微博热搜榜热度数据.csv',engine='python',skiprows=1,names=colnames)

    X=f.排名

    Y=f.numberdeffunc(p,x):

    a,b,c=preturn a*x*x+b*x+cdeferror_func(p,x,y):return func(p,x)-y

    p0=[0,0,0]

    Para=leastsq(error_func,p0,args=(X,Y))

    a,b,c=Para[0]

    plt.figure(figsize=(10,6))

    plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2)

    x=np.linspace(0,30,25)

    y=a*x*x+b*x+c

    plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2)

    plt.title("微博今日热搜排名和热度关系图")

    plt.xlabel('排名')

    plt.ylabel('热度(单位为万)')

    plt.legend()

    plt.show()

    four()

    6241488201a419296e800291c37eea5d.png

    5.完整代码:

    1 importrequests2 from lxml importetree3 importpandas as pd4 importnumpy as np5 importmatplotlib.pyplot as plt6 importmatplotlib7 from scipy.optimize importleastsq8 importscipy.stats as sts9 importseaborn as sns10

    11

    12 url = "https://tophub.today/"

    13 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'}14 html = requests.get(url,headers = headers)#发送get请求

    15 #print(html.text)#获取源代码

    16

    17

    18

    19 html = html.content.decode('utf-8')#配置编码

    20 html = etree.HTML(html)#构建一个xpath解析对象

    21

    22 div = html.xpath("//div[@id='node-1']/div")23 for a in div:#遍历标签

    24 titles = a.xpath(".//span[@class='t']/text()")#xpath正则表达

    25 numbers = a.xpath(".//span[@class='e']/text()")#xpath正则表达

    26

    27

    28

    29 b = []#创建一个空列表

    30 for i in range(25):31 b.append([i+1,titles[i],numbers[i][:-1]])#拷贝前25组数据

    32 file = pd.DataFrame(b,columns = ['排名','今日热搜','热度(单位为万)'])33 #print(file)

    34

    35 file.to_csv('微博热搜榜热度数据.csv',encoding = 'gbk')#保存文件,数据持久化

    36

    37

    38 #读取csv文件

    39 df = pd.DataFrame(pd.read_csv("微博热搜榜热度数据.csv",engine='python'))40 df.head()41

    42

    43 #删除无效列与行

    44 df.drop('今日热搜', axis=1, inplace=True)45 df.head()46

    47

    48 #空值处理

    49 df.isnull().sum()#返回0,表示没有空值

    50

    51

    52 #缺失值处理

    53 df[df.isnull().values==True]#返回无缺失值

    54

    55

    56

    57 #用describe()命令显示描述性统计指标

    58 df.describe()59

    60 #用corr()显示各数据间的相关系数

    61 df.corr()62

    63

    64 plt.rcParams['font.sans-serif'] = ['SimHei']65

    66 plt.rcParams['axes.unicode_minus'] =False67

    68

    69 #用seabron.lmplot()方法,建立排名和热度(单位为万)之间的线性关系

    70 sns.lmplot(x='排名',y='热度(单位为万)',data=df)71

    72

    73

    74 #绘制排名与热度条形图

    75 defone():76 file_path = "'微博热搜榜热度数据.csv'"

    77 x = df['排名']78 y = df['热度(单位为万)']79 plt.xlabel('排名')80 plt.ylabel('热度(单位为万)')81 plt.bar(x,y)82 plt.title("绘制排名与热度条形图")83 plt.show()84 one()85

    86

    87

    88 #绘制排名与热度折线图

    89 deftwo():90 x = df['排名']91 y = df['热度(单位为万)']92 plt.xlabel('排名')93 plt.ylabel('热度(单位为万)')94 plt.plot(x,y)95 plt.scatter(x,y)96 plt.title("绘制排名与热度折线图")97 plt.show()98 two()99

    100

    101 #绘制排名与热度散点图

    102 defthree():103 x = df['排名']104 y = df['热度(单位为万)']105 plt.xlabel('排名')106 plt.ylabel('热度(单位为万)')107 plt.scatter(x,y,color="red",label=u"热度分布数据",linewidth=2)108 plt.title("绘制排名与热度散点图")109 plt.legend()110 plt.show()111 three()112

    113

    114 #绘制一元一次方程

    115 defmain():116 colnames = ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)'

    117 f = pd.read_csv('微博热搜榜热度数据.csv',engine='python',skiprows=1,names=colnames)118 X =f.排名119 Y =f.number120

    121

    122 deffunc(p,x):123 k,b =p124 return k*x+b125

    126

    127 deferror_func(p,x,y):128 return func(p,x)-y129 p0 = [1,20]130 Para = leastsq(error_func,p0,args =(X,Y))131 k,b =Para[0]132

    133 print("k=",k,"b=",b)134

    135 plt.figure(figsize=(8,6))136 plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2)137 x=np.linspace(0,30,25)138 y=k*x+b139

    140 plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2)141 plt.title("微博今日热搜排名和热度关系图")142 plt.xlabel('排名')143 plt.ylabel('热度(单位为万)')144 plt.legend()145 plt.show()146 main()147

    148

    149 #绘制一元二次方程

    150 deffour():151

    152 colnames = ["排名","今日热搜","number"] #由于运行存在问题,用number表示'热度(单位为万)'

    153 f = pd.read_csv('微博热搜榜热度数据.csv',engine='python',skiprows=1,names=colnames)154 X =f.排名155 Y =f.number156

    157 deffunc(p,x):158 a,b,c=p159 return a*x*x+b*x+c160

    161 deferror_func(p,x,y):162 return func(p,x)-y163

    164 p0=[0,0,0]165 Para=leastsq(error_func,p0,args=(X,Y))166 a,b,c=Para[0]167 plt.figure(figsize=(10,6))168 plt.scatter(X,Y,color="green",label=u"热度分布",linewidth=2)169

    170 x=np.linspace(0,30,25)171 y=a*x*x+b*x+c172

    173 plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2)174 plt.title("微博今日热搜排名和热度关系图")175 plt.xlabel('排名')176 plt.ylabel('热度(单位为万)')177 plt.legend()178 plt.show()179

    180 four()

    总结:通过方程图可以更直观的看出热搜与热度之间的关系

    展开全文
  • hot-words-detection-with-MapReduce 使用Java MapReduce实现热词发现 代码库Github链接为:https://github.com/Resulte/hot-words-detection-with-MapReduce (希望您去Github的时候可以顺手给个Star) 介绍 热词...
  • 原标题:一个词推荐的简单实现为什么想做这个东西一直好奇像亚马逊这类网站的搜索是如何做到推荐的,最近刚好看到一篇文章《 Redis 与搜索词推荐 》,然而只写了思路。所以,就是想自己实现一个。先上个效果图,...
  • 1.添加热搜词功能 1.数据库表结构分析 热搜词表一共有三个字段,分别为主键id,搜索的关键词,及该关键字被搜索的次数 2.需求分析 当用户在前端进行搜索操作的时候,我们需要对该关键字进行判断,去根据搜索内容去表...
  • redis实现热搜

    2021-05-30 12:39:30
    一个项目中,遇到了搜索词统计的需求,我使用了 Redis 的五大数据类型之一 Sorted Set 实现。目前有两项数据需要统计:“当日搜索词 top10”和“当周搜索词 top10”。 关于这两项数据的统计方法,目前想到了两...
  • NULL 博文链接:https://m635674608.iteye.com/blog/2231884
  • 高级检索三 热搜词1.思路2.DSL语句3.java代码实现四 拼音补全1.DSL语法2.java代码实现总结 前言 前面讲了springboot集成ES的两种方法和es简单的增删改查,那么针对高级检索,es在7.x推荐的restclinet采用的查询方式...
  • 根据上述的简单需求,我就想用原生JAVA通过某些数据结构实现,由于知识面有限且笔者目前是名在校的学生,实现了英文下的分词、中文下的分词。但是遇到中英文混排的怎么也合并不了。经过两天的各种思考各种分析结果以...
  • java爬虫爬取微博热搜

    千次阅读 2017-12-10 16:03:20
    在网上稍微看了一下,好像还没有爬取微博热搜java实例,心血来潮就动手写一个简易版的,之后会不会升级再说。 首先我们点开微博热搜榜电脑版,然后查看源码。 我们可以看到body的构成很简单,几乎没有什么东西,...
  • 利用上次爬取的微博热搜榜单进行改进,对微博热搜榜单进行数据分析,额外爬取了榜单的热度值本次实现的主要问题在于图像的正确表现上一是对于字符串在图表上如何实现,另一是标题字符串过长的问题对于字符串的写入,...
  • redis 实现搜索词统计

    千次阅读 2020-06-03 14:28:45
    一个项目中,遇到了搜索词统计的需求,我使用了 Redis 的五大数据类型之一 Sorted Set 实现。目前有两项数据需要统计:“当日搜索词 top10”和“当周搜索词 top10”。 关于这两项数据的统计方法,目前想到了两...
  • 如何使用redis实现微博热搜

    千次阅读 2020-04-25 17:39:12
    前言 搜索的功能其实每个网站或者app都会有,前面笔者就使用elasticsearch+ik做了一个全文检索的搜索功能,...然后就想着把搜索词做一个热搜榜也不错,就开始动起手了 1.配置redisTemplate spring 封装了 RedisTempl...
  • java动态加载jar实现热拔插

    千次阅读 2020-08-07 15:12:26
    这是一篇关于项目经验积累的文章,在实际的项目中我们常常会遇到很多的问题,可能有很多种不同的解决...有这么一个需求,我们提供一个接口标准,写成了一个jar,这个标准给不同的厂商去实现实现完了打成一个jar,.
  • 使用java和redis实现一个简单的热搜功能,具备以下功能: 1:搜索栏展示当前登陆的个人用户的搜索历史记录,删除个人历史记录 2:用户在搜索栏输入某字符,则将该字符记录下来 以zset格式存储的redis中,记录该字符...
  • 突发奇想在我的小平台上添加一个文件下载排行榜,类似于百度的热搜(如下图)。 方案 使用LRU算法实现,该方案就是在内存中维护一个双向链表。将页面准备展示的排行榜的最小名次(例如:上图中的15就是最小名词)...
  • import java .util .* ; @RestController @RequestMapping( "/hotKey" ) public class HotKeyController { private Logger logger = LoggerFactory .getLogger (this .getClass ()) ; @Resource(name = ...
  • java实现站内搜索

    千次阅读 2013-04-16 22:10:10
    我们首先想到的问题是模糊匹配的原则,这样会有两种方式我们可以解决,一种是通过数据库的方式来实现, 一种是通过java提供的match来显示。 下面是我的通过数据库的方式来实现的, 个人认为这样实现比较直观易懂 ...
  • 你知道这个功能是如何实现的吗? 实际上,它的实现并不复杂。搜索引擎每天会接收大量的用户搜索请求,它会把这些用户输入的搜索关键词记录下来,然后再离线地统计分析,得到最热门的 Top 10 搜索关键词。 那请你...
  • Java中通过redis实现每日实时排行榜

    千次阅读 2022-04-08 15:17:15
    通过redis中zset类型来实现每日排行榜还是比较容易的,但也有一些地方需要注意。 具体实现代码如下: 1.设置数据 首先是要把需要的数据设置到redis中,注意分值前面的负号,由于zset特性是越小排到越前,所以分值...
  • 开头废话 一直想实现一个原创的热部署功能,其实Spring Loader,还有Tomcat都实现了相关...要实现热替换,一般想到的是实现classLoader(如果您对ClassLoader还不是很了解的,请查阅这篇博客https://www.ibm.com/de...
  • 开发:Java,TransportClient http://blog.csdn.net/tianzhaixing2013/article/details/51506496 这篇文章是es2.x版本+IK的近义词配置教程,es5.1的话一些地方还不一样。我从这篇文章中学到了不少,在此谢谢作者。 ...
  • smart_search_box是java领域的一站式搜索引擎解决方案,用户只需要进行简单的配置就可以在项目中引入完整的全文搜索能力,包括数据入库自动索引,搜索词联想,词提示,高亮等功能。同时提供给用户高度的自定义能力...
  • 华为机试高频题目(Java实现

    万次阅读 多人点赞 2022-04-02 22:56:39
    代码是Java实现。 首先对于华为机试的OJ输入输出需要熟练,可以参考: ACM(OJ)模式下对于各种输入输出情况的总结(JAVA) 华为机试高频题目: 类别 题目 知识点 题目分值 / 难度 字符串 华为机试:TLV...
  • Java 方式实现词云显示

    千次阅读 2020-07-29 21:17:32
    实现词云图2种方式word_cloud、stylecloud word_cloud :http://amueller.github.io/word_cloud/ stylecloud :https://github.com/minimaxir/stylecloud 1、需要先添加一下maven依赖 <dependency> <...
  • Double score(K key, Object o):获取指定成员的score值 二、代码实现 1、添加依赖 org.springframework.boot spring-boot-starter-data-redis 2、注入RedisTemplate方法 @Autowired public RedisTemplate ...
  • Idea Java 项目如何实现热部署

    千次阅读 2019-08-05 10:38:37
    java 项目在Idea里有很多种部署方式,但是有时候我们会发现,当你按照网上的方式设置好之后却并不起作用,今天来说一下我如何实现的 1.修改服务器配置,在Idea窗口失去焦点时,更新类和资源 Tomcat -> Edit...
  • java热修复实例

    千次阅读 2017-04-21 17:36:02
    关于java热修复的一次尝试

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,872
精华内容 12,748
关键字:

java实现热搜

java 订阅