【问题标题】:Better Design Pattern?更好的设计模式?
【发布时间】:2016-04-26 20:17:15
【问题描述】:

我的 myArrayList 中已经有值。对于此示例,假设其中只有两个元素(名字和姓氏)。我需要从 myArrayList 中获取值并将它们与 String 进行比较,如果匹配,则从 bean 中获取值并将其放入 map:

        Map<String,String> myMap;
        for(String element: myArrayList){
               if(element.equalsIgnoreCase("firstName")){
                   myMap.put("firstName", bean.getFirstName());
               }else if(element.equalsIgnoreCase("lastName")){
                   myMap.put("lastName", bean.getLastName());
               }
        }

问题是当你在 myArrayList 中有三十四十个元素时,你会遇到性能问题(我假设),而且感觉不对。

我试过了:

        String name = null;
        String value = null;
        for(int i = 0; i < myArrayList.size(); i++){
            name = myArrayList.get(i);
            value = bean.get(name);
            myMap.put(name, value);
        }

但是“value = bean.get(name);”这一行就是说 bean 类中的 get(String) 方法是未定义的,实际上我们在 bean 类中没有这样的方法,它只有标准的 getter 和 setter 方法:

public class Bean implements Serializable {
    private String firstName;
    private String lastName;

    public String getFirstName(){
        return firstName;
    }

    public void setFirstName(String firstName){
        this.firstName = firstName;
    }

    public String getLastName(){
        return lastName;
    }

    public void setLastName(String lastName){
        this.lastName = lastName;
    }

}

现在我正在考虑如何提出一些设计模式来优化我的逻辑并且不影响代码的性能。请随时提出问题,如果您需要更多信息,我会编辑。任何帮助是极大的赞赏。谢谢。

编辑:shmosel 的回答对我来说非常好,谢谢大家的帮助!干杯!

【问题讨论】:

  • 30-40 个元素不会从优化中看到太多改进,但 1000 个元素会。 (如果它意味着更优雅的代码,优化仍然很好)
  • 您似乎正在尝试使用反射来获取 bean 属性。您可能会参考stackoverflow.com/questions/5856895/…,但请注意,使用反射会产生一些性能开销。如果您使用的是 Java 8,则可以使用 ("lastName",Bean::getLastName) 之类的值创建一个 HashMap> 以按名称快速查找字段访问器。

标签: java design-patterns javabeans


【解决方案1】:

@HankD 和 @Natalia 提供了一些有效的解决方案,但我没有看到提到的另一个选项是重构 Bean 以支持 get(String) 方法:

public class Bean implements Serializable {
    private Map<String, String> properties = new HashMap<>();

    public String get(String property) {
        return properties.get(property);
    }

    public void set(String property, String value) {
        properties.put(property, value);
    }

    public String getFirstName(){
        return get("firstName");
    }

    public void setFirstName(String firstName){
        set("firstName", firstName);
    }

    public String getLastName(){
        return get("lastName");
    }

    public void setLastName(String lastName){
        set("lastName", lastName);
    }

}

【讨论】:

  • 我真的很喜欢这个解决方案。这很容易理解,但它也没有强制人们可以存储哪些属性,而且感觉很脏。另外,我不确定这是否会是一种优化。
  • 如果要限制属性集,请使用枚举而不是字符串作为属性字段。
  • @4castle, set() 可以设为私有以限制属性。尽管我的目标不是优化(我怀疑这是否真的是 OP 的目标),但我希望 get() 的性能会比 if-else 链更好。开关可能不同。
  • @TimWilliscroft 枚举将需要包装一个字符串值,否则我们将回到原点。
  • 我的意思是这可能是一个更不理想的解决方案。它降低了所有吸气剂的速度,而不是仅仅降低了get。诚然,确实不需要优化,这就是它没什么大不了的原因。
【解决方案2】:

你可以尝试使用反射see javaDoc

但是,除非真的需要,否则我不建议使用它。可能的,你应该重构你的代码以避免有你需要得到的字段列表。

如果你决定使用反射,springframework 中有 ReflectionUtils

【讨论】:

    【解决方案3】:

    您的get(String) 方法是一个非常好的主意,它只需要正确完成。这是我的做法,它与您在Bean 之外所做的非常相似,但它允许分离关注点,这是一件好事。

    public String get(String field) {
        switch(field.toLowerCase()) {
            case "firstname":
                return firstName;
            case "lastname":
                return lastName;
            default:
                throw new IllegalArgumentException(field + " is an invalid field name.");
        }
    }
    

    我在这里使用switch 语句,因为Java Docs 请注意:

    Java 编译器从使用 String 对象的 switch 语句生成的字节码通常比从链式 if-then-else 语句生成的字节码更有效。

    如果您无法更改 Bean 类,那么您至少应该在循环中使用此逻辑而不是当前逻辑,以提高 switch 语句的速度并调用 toLowerCase() 一次而不是使用equalsIgnoreCase() 多次。

    【讨论】:

    • 非常感谢您的回答,但在我的情况下,shmosel 的回答似乎更好。再次感谢。
    【解决方案4】:

    这似乎是一种奇怪的做事方式。正如 4castle 所指出的,一些元素本身不太可能导致性能问题。您是否遇到性能问题?

    如果是我,我会这样做:

    public static final String lastNameValue = "lastname";
    
    for(String element: myArrayList){
        if(element != null) element = element.toLowerCase();
    
        if(lastNameValue.equals(element){
            myMap.put("lastName", bean.getLastName());
        } ....
    }
    

    每次调用此方法时,常量都会阻止构造新字符串。您没有检查空元素。执行一次 toLowerCase() 比执行多次更有效。

    【讨论】:

    • 谁在构建新字符串?
    猜你喜欢
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多