Java 函数解代替迭代解

Java 函数解代替迭代解,java,java-8,functional-programming,Java,Java 8,Functional Programming,我必须执行以下任务。为了简单起见,我创建了下表: 我们有输入和一个定义了规则的表。如果有任何规则与此输入匹配,则对其应用操作 例如,输入HBC1234: 以H=>true开始 因此,将匹配的_值(H)替换为M=>结果是MBC1234 以相同的方式迭代此输入的所有其他规则 以下是替换规则的实体: @Data @Entity @NoArgsConstructor public class ReplacementRule implements Serializable { private s

我必须执行以下任务。为了简单起见,我创建了下表:

我们有输入和一个定义了规则的表。如果有任何规则与此输入匹配,则对其应用操作

例如,输入
HBC1234

  • 以H=>true开始
  • 因此,将匹配的_值(H)替换为
    M
    =>结果是
    MBC1234
  • 以相同的方式迭代此输入的所有其他规则

    以下是替换规则的实体:

    @Data
    @Entity
    @NoArgsConstructor
    public class ReplacementRule implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        @NotNull
        @Enumerated(EnumType.STRING)
        private MatchingOperation matchingOperation;
        @NotNull
        private String matchingValue;
    
        @NotNull
        @Enumerated(EnumType.STRING)
        private ReplacementOperation replacementOperation;
        private String replacementValue;
    }
    
    这项任务的执行情况:

    private static String apply(ReplacementRule rule, String plateNumber) {
        switch (rule.getMatchingOperation()) {
            case STARTS_WITH:
                if (plateNumber.startsWith(rule.getMatchingValue())) {
                    return switch (rule.getReplacementOperation()) {
                        case REPLACE -> plateNumber.replaceFirst(rule.getMatchingValue(), rule.getReplacementValue());
                        case REMOVE -> plateNumber.substring(rule.getMatchingValue().length());
                    };
                }
            case CONTAINS:
                if (plateNumber.contains(rule.getMatchingValue())) {
                    return switch (rule.getReplacementOperation()) {
                        case REPLACE -> plateNumber.replaceAll(rule.getMatchingValue(), rule.getReplacementValue());
                        case REMOVE -> plateNumber.replaceAll(rule.getMatchingValue(), "");
                    };
                }
            case ENDS_WITH:
                if (plateNumber.endsWith(rule.getMatchingValue())) {
                    return switch (rule.getReplacementOperation()) {
                        case REPLACE -> plateNumber.substring(0, getEndIndex(rule, plateNumber)).concat(rule.getReplacementValue());
                        case REMOVE -> plateNumber.substring(0, getEndIndex(rule, plateNumber));
                    };
                }
            case EQUALS:
                if (plateNumber.equals(rule.getMatchingValue())) {
                    return switch (rule.getReplacementOperation()) {
                        case REPLACE -> rule.getReplacementValue();
                        case REMOVE -> "";
                    };
                }
        }
        return "";
    }
    
    private static int getEndIndex(ReplacementRule rule, String plateNumber) {
        return plateNumber.length() - rule.getMatchingValue().length();
    }
    
    最终用法如下所示:

    public Optional<WhiteList> checkReplacementRules(String plateNumber) {
        List<ReplacementRule> allRules = ruleRepository.findAll();
    
        Optional<WhiteList> result = Optional.empty();
        for (ReplacementRule rule : allRules) {
            String newPlate = transform(rule, plateNumber);
            if (StringUtils.isNotBlank(newPlate)) {
                result = whiteListRepository.findByNumberPlate(newPlate);
            }
        }
    
        return result;
    }
    
    public可选checkReplacementRules(字符串编号){
    List allRules=ruleRepository.findAll();
    可选结果=可选。空();
    for(替换规则:所有规则){
    字符串newPlate=变换(规则、板材编号);
    如果(StringUtils.isNotBlank(newPlate)){
    结果=whiteListRepository.findByNumberPlate(newPlate);
    }
    }
    返回结果;
    }
    
    它将匹配和逻辑结合起来,在一个方法中进行替换
    apply()
    。然而,它违反了法律。但它是有效的。尽管这个解决方案不是最好的

    这种任务似乎与函数式编程概念相匹配

    如何将其重新设计为功能性风格


    Java版本是15

    enum
    类实现操作,即操作

    正则表达式似乎非常适合你所做的事情

    私有静态字符串应用(替换规则,字符串编号){
    字符串regex=rule.getMatchingOperation().regexFor(rule.getMatchingValue());
    字符串替换=rule.getReplacementOperation().regexFor(rule.getReplacementValue());
    返回模式.compile(regex)
    .匹配器(板号)
    .replaceFirst(替换);
    }
    
    公共枚举匹配操作{
    以(v->“^”+模式开头。引号(v)),
    包含(v->Pattern.quote(v)),
    以(v->Pattern.quote(v)+“$”)结束,
    等于(v->“^”+模式。引号(v)+“$”;
    私人最终一元运算符asRegex;
    专用匹配操作(UnaryOperator asRegex){
    this.asRegex=asRegex;
    }
    公共字符串regexFor(字符串匹配值){
    返回此.asRegex.apply(匹配值);
    }
    }
    
    公共枚举替换操作{
    替换(匹配器::引用替换),
    移除(v->”);
    私人最终一元运算符asRegex;
    专用替换操作(UnaryOperator asRegex){
    this.asRegex=asRegex;
    }
    公共字符串regexFor(字符串替换值){
    返回此.asRegex.apply(replacementValue);
    }
    }
    
    enum
    类实现操作,即操作

    正则表达式似乎非常适合你所做的事情

    私有静态字符串应用(替换规则,字符串编号){
    字符串regex=rule.getMatchingOperation().regexFor(rule.getMatchingValue());
    字符串替换=rule.getReplacementOperation().regexFor(rule.getReplacementValue());
    返回模式.compile(regex)
    .匹配器(板号)
    .replaceFirst(替换);
    }
    
    公共枚举匹配操作{
    以(v->“^”+模式开头。引号(v)),
    包含(v->Pattern.quote(v)),
    以(v->Pattern.quote(v)+“$”)结束,
    等于(v->“^”+模式。引号(v)+“$”;
    私人最终一元运算符asRegex;
    专用匹配操作(UnaryOperator asRegex){
    this.asRegex=asRegex;
    }
    公共字符串regexFor(字符串匹配值){
    返回此.asRegex.apply(匹配值);
    }
    }
    
    公共枚举替换操作{
    替换(匹配器::引用替换),
    移除(v->”);
    私人最终一元运算符asRegex;
    专用替换操作(UnaryOperator asRegex){
    this.asRegex=asRegex;
    }
    公共字符串regexFor(字符串替换值){
    返回此.asRegex.apply(replacementValue);
    }
    }
    
    我不认为您的设计违反了开闭原则,但是,下面是我的实现。由于它可以将未来的需求添加为功能,因此可以称为功能性需求

    @FunctionalInterface
    interface Rule {
        public String apply(String string);
    }
    
    规则
    适用于每个需求的功能

    class Replacement {
        ArrayList<Rule> rules = new ArrayList<Rule>();
    
        public Replacement addRule(Rule rule) {
            rules.add(rule);
            return this;
        }
        
        public String applyAll(String string) {
            System.out.printf("%s --> ", string);
            for (Rule rule : rules) {
                string = rule.apply(string);
            }   
            System.out.println(string);
            return string;
        }
    }
    

    我不认为您的设计违反了开闭原则,但是,下面是我的实现。由于它可以将未来的需求添加为功能,因此可以称为功能性需求

    @FunctionalInterface
    interface Rule {
        public String apply(String string);
    }
    
    规则
    适用于每个需求的功能

    class Replacement {
        ArrayList<Rule> rules = new ArrayList<Rule>();
    
        public Replacement addRule(Rule rule) {
            rules.add(rule);
            return this;
        }
        
        public String applyAll(String string) {
            System.out.printf("%s --> ", string);
            for (Rule rule : rules) {
                string = rule.apply(string);
            }   
            System.out.println(string);
            return string;
        }
    }
    

    为什么你认为它违反了开放-封闭原则<代码> >案例< /代码> S将被添加吗?将来添加哪些需求/条件总是不可预测的。如果添加了新的需求,是否可以避免更改代码?我认为您的代码可以始终如一地添加规则并满足需求。“替换操作”的抽象真的有必要吗?删除和删除之间没有区别“用一个空字符串替换”,字符串无论如何都被携带。“霍格尔好,为什么你认为它违反了开放的封闭原理?”代码>用例< /代码> S将会被添加吗?[可预测未来将添加哪些需求/条件。如果添加新的需求,是否可以避免更改代码?我认为您的代码可以始终添加规则并满足需求。“替换操作”的抽象真的有必要吗?删除和删除之间没有区别“替换为空字符串”并且字符串仍然被携带。@Holger good Shot不使用
    UnaryOperator
    Pattern.compile
    在类外,使用
    函数
    更有意义。然后可以使用
    Pattern.compile(v,Pattern.LITERAL)
    for
    包含
    。最好包含实际匹配的op