拼音转汉字、SpEL表达式、汉字转拼音

一、SpEL语法案例

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.PropertyPlaceholderHelper;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class PlaceholderResolver {

    public static void main(String[] args) throws NoSuchMethodException {
        ExpressionParser parser = new SpelExpressionParser();
       //字符串解析
        String str = (String) parser.parseExpression("'你好'").getValue();
        System.out.println(str);
        //整型解析
        int intVal = (Integer) parser.parseExpression("0x2F").getValue();
        System.out.println(intVal);
        //双精度浮点型解析
        double doubleVal = (Double) parser.parseExpression("4329759E+22").getValue();
        System.out.println(doubleVal);
        //布尔型解析
        boolean booleanVal = (boolean) parser.parseExpression("true").getValue();
        System.out.println(booleanVal);
        //执行表达式,默认容器是spring本身的容器:ApplicationContext
        List<Integer> result1 = parser.parseExpression("{1,2,3}").getValue(List.class);
        //等同于如下java代码
        Integer[] integer = new Integer[]{1,2,3};
        List<Integer> result2 = Arrays.asList(integer);
        //创建ctx容器
        StandardEvaluationContext ctx = new StandardEvaluationContext();
        //获取java自带的Integer类的parseInt(String)方法
        Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);
        //将parseInt方法注册在ctx容器内, 推荐这样使用
        ctx.registerFunction("parseInt", parseInt);
        //再将parseInt方法设为parseInt2
        ctx.setVariable("parseInt2", parseInt);
        //创建ExpressionParser解析表达式
        ExpressionParser parsers = new SpelExpressionParser();
        //SpEL语法,比对两个方法执行完成后,结果是否相同
        String expressionString = "#parseInt('2') == #parseInt2('3')";
        //执行SpEL
        Expression expression = parsers.parseExpression(expressionString);
        Boolean values = expression.getValue(ctx, Boolean.class);
        System.out.println(values);
    }


    private static final PropertyPlaceholderHelper defaultHelper = new PropertyPlaceholderHelper("${", "}");
    private static PlaceholderResolver defaultResolver = new PlaceholderResolver();

    private PropertyPlaceholderHelper propertyPlaceholderHelper;


    private PlaceholderResolver() {
        propertyPlaceholderHelper = defaultHelper;
    }

    private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) {
        propertyPlaceholderHelper = new PropertyPlaceholderHelper(placeholderPrefix, placeholderSuffix);
    }

    /**
     * 获取默认的占位符解析器,即占位符前缀为"${", 后缀为"}"
     *
     * @return
     */
    public static PlaceholderResolver getDefaultResolver() {
        return defaultResolver;
    }

    public static PlaceholderResolver getResolver(String placeholderPrefix, String placeholderSuffix) {
        return new PlaceholderResolver(placeholderPrefix, placeholderSuffix);
    }

    /**
     * 解析带有指定占位符的模板字符串
     * 如:content =  ${0}今年${1}岁
* values = {"xiaoming", "18"}
* result 小明今年18岁
* * @param content 要解析的带有占位符的模板字符串 * @param values 按照模板占位符索引位置设置对应的值 * @return */
public String resolve(String content, String... values) { return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> { return values[Integer.valueOf(placeholderName)]; }); } /** * 解析带有指定占位符的模板字符串 * 如:content = ${0}今年${1}岁
* values = {"xiaoming", "18"}
* result 小明今年18岁
* * @param content 要解析的带有占位符的模板字符串 * @param values 按照模板占位符索引位置设置对应的值 * @return */
public String resolve(String content, Object[] values) { return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> { return String.valueOf(values[Integer.valueOf(placeholderName)]); }); } /** * 根据替换规则来替换指定模板中的占位符值 * * @param content 要解析的字符串 * @param placeholderResolver 解析规则回调 * @return */ public String resolveByRule(String content, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver) { return propertyPlaceholderHelper.replacePlaceholders(content, placeholderResolver); } /** * 替换模板中占位符内容,占位符的内容即为map key对应的值,key为占位符中的内容。

* 如:content = ${name}今年${age}岁
* valueMap = name -> 小明; age -> 18
* result 小明今年18岁
* * @param content 模板内容。 * @param valueMap 值映射 * @return 替换完成后的字符串。 */
public String resolveByMap(String content, final Map<String, Object> valueMap) { return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> { return String.valueOf(valueMap.get(placeholderName)); }); } /** * 根据对象中字段路径(即类似js访问对象属性值)替换模板中的占位符

* 如 content = product:${id}:detail:${detail.id}
* obj = Product.builder().id(1).detail(Detail.builder().id(2).build()).build();
* 经过解析返回 product:1:detail:2
* * @param content 要解析的内容 * @param obj 填充解析内容的对象(如果是基本类型,则所有占位符都替换为当前基本类型) * @return */
public String resolveByObject(String content, final Object obj) { if (obj instanceof Map) { return resolveByMap(content, (Map) obj); } return propertyPlaceholderHelper.replacePlaceholders(content, placeholderName -> { return String.valueOf(getValueByFieldPath(obj, placeholderName)); }); } /** * 获取指定对象中指定字段路径的值 * $(user.name) * * @param obj 取值对象 * @param fieldPath 字段路径(形如 user.name) * @return */ private Object getValueByFieldPath(Object obj, String fieldPath) { String[] fieldNames = fieldPath.split("\\."); Object result = null; for (String fieldName : fieldNames) { result = getFieldValue(obj, fieldName); if (result == null) { throw new RuntimeException(fieldName + "为空!"); } obj = result; } return result; } private Object getFieldValue(Object obj, String fieldName) { Class clazz = obj.getClass(); if (isBaseType(clazz)) { return obj; } while (clazz != Object.class && clazz != null) { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } catch (NoSuchFieldException e) { clazz = clazz.getSuperclass(); } catch (IllegalAccessException e) { throw new RuntimeException("无法访问 " + fieldName); } } throw new IllegalStateException(fieldName + "字段不存在!"); } /** * 判断class是否为常用类型 * * @param clazz * @return */ private boolean isBaseType(Class clazz) { return Enum.class.isAssignableFrom(clazz) || CharSequence.class.isAssignableFrom(clazz) || Number.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz); } /** * 打码隐藏加* * * @param num 号码 * @param front 需要显示前几位 * @param end 需要显示末几位 * @return */ public static String mask(String num, int front, int end) { // 传入的号码不能为空 if (num == null || num.length() <= 0) { return null; } // 需要截取的长度不能大于号码长度 if ((front + end) > num.length()) { return null; } //需要截取的不能小于0 if (front < 0 || end < 0) { return null; } //计算*的数量 int asteriskCount = num.length() - (front + end); StringBuffer asteriskStr = new StringBuffer(); for (int i = 0; i < asteriskCount; i++) { asteriskStr.append("*"); } String regex = "(\\w{" + front + "})(\\w+)(\\w{" + end + "})"; // $1、$2、……表示正则表达式里面第一个、第二个、……括号里面的匹配内容 return num.replaceAll(regex, "$1" + asteriskStr + "$3"); } }

二、汉字转拼音

       <dependency>
            <groupId>com.belerweb</groupId>
            <artifactId>pinyin4j</artifactId>
            <version>2.5.0</version>
        </dependency>
       <dependency>
	       <groupId>com.github.stuxuhai</groupId>
	       <artifactId>jpinyin</artifactId>
	       <version>1.1.7</version>
       </dependency>
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
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;

@Slf4j
public class Pinyin4jUtil {

    /**
     * getFirstSpellPinYin:(多音字的时候获取第一个). 
* @param src 传入的拼音字符串,以逗号隔开 * @param isFullSpell 是否全拼,true:全拼,false:第一个汉字全拼(其它汉字取首字母) * @return 第一个拼音 */
public static String getFirstSpellPinYin(String src, boolean isFullSpell) { String targetStr = Pinyin4jUtil.makeStringByStringSet(Pinyin4jUtil.getPinyin(src, isFullSpell)); String[] split = targetStr.split(","); if (split.length > 1) { targetStr = split[0]; } return targetStr; } /** * makeStringByStringSet:(拼音字符串集合转换字符串(逗号分隔)).
* @param stringSet 拼音集合 * @return 带逗号字符串 */
public static String makeStringByStringSet(Set<String> stringSet) { StringBuilder str = new StringBuilder(); int i = 0; if (stringSet.size() > 0) { for (String s : stringSet) { if (i == stringSet.size() - 1) { str.append(s); } else { str.append(s + ","); } i++; } } return str.toString().toLowerCase(); } /** * getPinyin:(获取汉字拼音).
* @param src 汉字 * @param isFullSpell 是否全拼,如果为true:全拼,false:首字全拼 * @return */
public static Set<String> getPinyin(String src, boolean isFullSpell) { if (src != null && !src.trim().equalsIgnoreCase("")) { char[] srcChar; srcChar = src.toCharArray(); // 汉语拼音格式输出类 HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat(); // 输出设置,大小写,音标方式等 hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V); String[][] temp = new String[src.length()][]; for (int i = 0; i < srcChar.length; i++) { char c = srcChar[i]; if (String.valueOf(c).matches("[\\u4E00-\\u9FA5]+")) { //中文 try { temp[i] = PinyinHelper.toHanyuPinyinStringArray( srcChar[i], hanYuPinOutputFormat); if (!isFullSpell) { if (i == 0) { temp[i] = temp[i]; } else { String[] tTemps = new String[temp[i].length]; for (int j = 0; j < temp[i].length; j++) { char t = temp[i][j].charAt(0); tTemps[j] = Character.toString(t); } temp[i] = tTemps; } } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } //英文 } else if (((int) c >= 65 && (int) c <= 90) || ((int) c >= 97 && (int) c <= 122)) { temp[i] = new String[] { String.valueOf(srcChar[i]) }; } else { temp[i] = new String[] { "" }; } } String[] pingyinArray = exchange(temp); Set<String> pinyinSet = new HashSet<>(); for (int i = 0; i < pingyinArray.length; i++) { pinyinSet.add(pingyinArray[i]); } return pinyinSet; } return null; } /** * 递归 * @param strJaggedArray * @return */ public static String[] exchange(String[][] strJaggedArray) { String[][] temp = doExchange(strJaggedArray); return temp[0]; } /** * 递归 * @param strJaggedArray * @return */ private static String[][] doExchange(String[][] strJaggedArray) { int len = strJaggedArray.length; if (len >= 2) { int len1 = strJaggedArray[0].length; int len2 = strJaggedArray[1].length; int newlen = len1 * len2; String[] temp = new String[newlen]; int Index = 0; for (int i = 0; i < len1; i++) { for (int j = 0; j < len2; j++) { temp[Index] = strJaggedArray[0][i] + strJaggedArray[1][j]; Index++; } } String[][] newArray = new String[len - 1][]; for (int i = 2; i < len; i++) { newArray[i - 1] = strJaggedArray[i]; } newArray[0] = temp; return doExchange(newArray); } else { return strJaggedArray; } } /** * 判断是否是中文字符串 还是拼音或者英文字符串 * @param str * @return */ public static boolean isChinese(String str){ String regEx = "[\\u4e00-\\u9fa5]+"; Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(str); return m.find(); } /** * 将字符串转换成拼音数组 * * @param src * @return */ public static String[] stringToPinyin(String src) { return stringToPinyin(src, false, null); } /** * 将字符串转换成拼音数组 * * @param src * @return */ public static String[] stringToPinyin(String src, String separator) { return stringToPinyin(src, true, separator); } /** * 将字符串转换成拼音数组 * * @param src * @param isPolyphone * 是否查出多音字的所有拼音 * @param separator * 多音字拼音之间的分隔符 * @return */ public static String[] stringToPinyin(String src, boolean isPolyphone, String separator) { // 判断字符串是否为空 if ("".equals(src) || null == src) { return null; } char[] srcChar = src.toCharArray(); int srcCount = srcChar.length; String[] srcStr = new String[srcCount]; for (int i = 0; i < srcCount; i++) { srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator); } return srcStr; } /** * 将单个字符转换成拼音 * * @param src * @return */ public static String charToPinyin(char src, boolean isPolyphone, String separator) { // 创建汉语拼音处理类 HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); // 输出设置,大小写,音标方式 defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); StringBuffer tempPinying = new StringBuffer(); // 如果是中文 if (src > 128) { try { // 转换得出结果 String[] strs = PinyinHelper.toHanyuPinyinStringArray(src, defaultFormat); // 是否查出多音字,默认是查出多音字的第一个字符 if (isPolyphone && null != separator) { for (int i = 0; i < strs.length; i++) { tempPinying.append(strs[i]); if (strs.length != (i + 1)) { // 多音字之间用特殊符号间隔起来 tempPinying.append(separator); } } } else { tempPinying.append(strs[0]); } } catch (BadHanyuPinyinOutputFormatCombination e) { log.error("中文转拼音错误:{}",e); } } else { tempPinying.append(src); } return tempPinying.toString(); } public static void main(String[] args) { System.out.println(isChinese("你好呀")); System.out.println(JSON.toJSONString(stringToPinyin("你好呀"))); String string = Arrays.asList(stringToPinyin("你好呀")).stream().collect(Collectors.joining(" ")); System.out.println(string); } }

三、拼音转汉字

1、原理是viterbi算法、原理是词库+动态规划、搜狗语料库

参考:https://github.com/ranchlai/pinyin2hanzi
拼音转汉字、SpEL表达式、汉字转拼音_第1张图片2、喵搜输入法

参考:https://github.com/crownpku/Somiao-Pinyin
拼音转汉字、SpEL表达式、汉字转拼音_第2张图片
3、隐马尔科夫模型(HMM)实现的拼音转汉字

参考:https://github.com/KHN190/pinyin

你可能感兴趣的:(JAVA开发,算法,基础积累,拼音转汉字,SpEL表达式,汉字转拼音)