解析内容 if else太多 请问优化代码?

新手上路,请多包涵
//List<String> 内容
[ti:我本闺中一钗裙]
[oti:我本闺中一钗裙]
[jz:黄梅戏]
[jm:女驸马]
[ojm:女驸马]
[offset:-1]
[by:制作者]
[ver:驸马公主合唱]
[keys:民女,洞房]
[00:04.99](驸马):我本闺中一钗裙
[00:31.93](公主白):此话当真
[00:34.19](驸马):公主请看耳环痕
[00:59.33]<结束>

/**
     * 解析唱段内容
     *
     * @param changDuan  唱段对象
     * @param line       当前需要解析的内容 即上面 List<String> 每一行内容
     * @param patternMap 唱段正则表达式 可以正则匹配上面 List<String> 内容
     * @throws ParseLrcException
     */
private static void parseLrcContent(ChangDuan changDuan, String line, Map<String, Pattern> patternMap) throws ParseLrcException {

        if (matcher(line, patternMap, LrcConstants.LrcRegEnum.TITLE.name())) {
            changDuan.setName(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.TITLE.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.ORIGIN_TITLE.name())) {
            changDuan.setOriginName(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.ORIGIN_TITLE.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.JUMU.name())) {
            changDuan.setJuMu(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.JUMU.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.ORIGIN_JUMU.name())) {
            changDuan.setOriginJuMu(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.ORIGIN_JUMU.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.OFFSET_REG.name())) {
            changDuan.setOffset(Integer.parseInt(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.OFFSET_REG.getStartIndex())));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.JU_ZHONG.name())) {
            changDuan.setJuZhong(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.JU_ZHONG.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.BEIZHU.name())) {
            changDuan.setBeiZhu(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.BEIZHU.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.VERSION.name())) {
            changDuan.setVersion(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.VERSION.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.KEYS.name())) {
            changDuan.setSearchKeys(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.KEYS.getStartIndex()));
        } else if (matcher(line, patternMap, LrcConstants.LrcRegEnum.BY.name())) {
            changDuan.setMaker(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.BY.getStartIndex()));
        } else {
            throw new ParseLrcLineException(line);
        }
    }

上段代码是用于将List<String>解析成ChangDuan

想请教一下这个代码写的咋样,能否优化,我就是觉得if else太多了。

阅读 1.2k
avatarAI BotBETA

这段代码看起来是在处理歌词文件(LRC)的内容,对每一行歌词进行解析并填充到 ChangDuan 对象中。代码写得比较清晰,针对不同的歌词内容使用了不同的正则表达式进行匹配,然后提取相应的信息填充到 ChangDuan 对象中。

关于代码优化的问题,可以考虑以下几点:

  1. 使用 switch-case 语句:你可以将所有的 if-else 语句替换为 switch-case 语句,这会使代码更加清晰和易于管理。
  2. 提取公共方法:有些代码片段在 if-else 语句中反复出现,例如 matcher(line, patternMap, LrcConstants.LrcRegEnum.OFFSET_REG.name()),你可以将这些公共代码提取出来,单独写一个方法进行复用。
  3. 使用 Map 存储 LRC 内容和对应的属性:可以使用一个 Map 来存储 LRC 内容和对应的属性,这样可以直接通过属性名来获取内容,减少 if-else 判断的次数。
  4. 考虑使用策略模式:针对不同的 LRC 内容类型,可以考虑使用策略模式,为每种类型定义一个单独的解析策略类,减少 if-else 判断的复杂性。

下面是一个简化的示例代码,使用了 switch-case 语句和 Map 来优化代码:

private static void parseLrcContent(ChangDuan changDuan, String line, Map<String, Pattern> patternMap) throws ParseLrcException {
    switch (line) {
        case LrcConstants.LrcRegEnum.TITLE.name():
            changDuan.setName(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.TITLE.getStartIndex()));
            break;
        case LrcConstants.LrcRegEnum.ORIGIN_TITLE.name():
            changDuan.setOriginName(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.ORIGIN_TITLE.getStartIndex()));
            break;
        // ... 其他属性类似处理
        default:
            throw new ParseLrcLineException(line);
    }
}

此外,你还可以考虑使用一些开源的歌词解析库,例如 Jieba 的歌词解析库,这些库通常已经实现了歌词的解析和分词功能,可以减少自己编写的代码量。

2 个回答

抽象一个接口:

interface IMatchParser{
    boolean matcher(String line, Map<String, Patter> map);
    handle(ChangDuan changduan);
}

每个if分支抽象成一个类继承IMatchParser;

public class MatchParser1 implements IMatchParser{
    public void handle(ChangDuan changduan) {
        changDuan.setName(getChangDuanInfoContent(line, LrcConstants.LrcRegEnum.TITLE.getStartIndex()));
    }

    public boolean matcher(String line, Map<String, Patter> map) {
        return matcher(line, patternMap, LrcConstants.LrcRegEnum.TITLE.name());
    }
}

然后放到一个list中:

List<IMatchParser> list = new ArrayList();
list.add(new MatchParser1());
list.add(new MatchParser2());
...

然后实现方法变成:

private static void parseLrcContent(ChangDuan changDuan, String line, Map<String, Pattern> patternMap) throws ParseLrcException {
    for (IMatchParser parser: list) {
        if (parser.match(line, patternMap)) {
            parser.handle(changDuan);
            break;    
        }
    }
}

后续加新的if分支只需要实现一个新的class插入到list即可

使用表驱动设计模式即可

推荐问题