更好的设计模式?
Better Design Pattern?
我的 myArrayList 中已有值。对于这个例子,假设其中只有两个元素(firstName 和 lastName)。我需要从 myArrayList 获取值并将它们与 String 进行比较,如果匹配则从 bean 获取值并将其放入映射中:
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);" 说方法 get(String) 在 bean class 中未定义,实际上我们在 bean class 中没有这样的方法,它只有标准 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 的回答对我来说很好,谢谢大家的帮助!干杯!
这似乎是一种奇怪的做事方式。正如 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() 比多次执行更有效率。
你可以尝试使用反射see javaDoc
但是,我不推荐使用它,除非确实需要它。可能的话,你应该重构你的代码以避免有字段列表,你需要得到。
如果你决定使用反射,springframework中有ReflectionUtils
@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);
}
}
您的 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 注意:
The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
如果你不能改变你的 Bean
class,那么你至少应该在你的循环中使用这个逻辑而不是你当前的逻辑只是为了更好的速度 switch
语句并调用 toLowerCase()
一次,而不是多次使用 equalsIgnoreCase()
。
我的 myArrayList 中已有值。对于这个例子,假设其中只有两个元素(firstName 和 lastName)。我需要从 myArrayList 获取值并将它们与 String 进行比较,如果匹配则从 bean 获取值并将其放入映射中:
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);" 说方法 get(String) 在 bean class 中未定义,实际上我们在 bean class 中没有这样的方法,它只有标准 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 的回答对我来说很好,谢谢大家的帮助!干杯!
这似乎是一种奇怪的做事方式。正如 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() 比多次执行更有效率。
你可以尝试使用反射see javaDoc
但是,我不推荐使用它,除非确实需要它。可能的话,你应该重构你的代码以避免有字段列表,你需要得到。
如果你决定使用反射,springframework中有ReflectionUtils
@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);
}
}
您的 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 注意:
The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.
如果你不能改变你的 Bean
class,那么你至少应该在你的循环中使用这个逻辑而不是你当前的逻辑只是为了更好的速度 switch
语句并调用 toLowerCase()
一次,而不是多次使用 equalsIgnoreCase()
。