问题
之前写了一个小的燃烧计算程序,其中有一部分是为了计算混合组分的特性参数,用了下面的一些代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public interface ComponentCal extends Map<String, Double> { public double getDensity();
public double getQd();
public double getQg();
public double getL_O2();
public double getCp(double temperature);
public double getC();
public double getH(); }
|
其中各get
方法是读取各成分各自的特性参数,然后计算成混合组分的参数。
方法一
最开始写的时候用最苯的方法,用是for-each
方法读取每个,然后sum
方法求和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class GasComponent extends HashMap<String, Double> implements ComponentCal {
private PropertyRepository propertyRepository;
@Inject public void setPropertyRepository(PropertyRepository propertyRepository) { this.propertyRepository = propertyRepository; }
public double getDensity() { double sum = 0.0; for (Entry<String, Double> item : this.entrySet()) { sum += propertyRepository.getByName(item.getKey()).getDensity() * item.getValue(); } return sum * 0.01; }
public double getQd() { double sum = 0.0; for (Entry<String, Double> item : this.entrySet()) { sum += propertyRepository.getByName(item.getKey()).getQd() * item.getValue(); } return sum; }
}
|
方法二
用lambda
取代for-each
,这个感觉和C#的LINQ
很像哦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class GasComponent extends HashMap<String, Double> implements ComponentCal {
private PropertyRepository propertyRepository;
@Inject public void setPropertyRepository(PropertyRepository propertyRepository) { this.propertyRepository = propertyRepository; }
public double getDensity() { return this.entrySet().stream().mapToDouble(item -> propertyRepository.getByName(item.getKey()).getDensity() * item.getValue()).sum() * 0.01; }
public double getQd() { return this.entrySet().stream().mapToDouble(item -> propertyRepository.getByName(item.getKey()).getQd() * item.getValue()).sum(); }
}
|
方法三
上面GasComponent
实现ComponentCal
各个get
方法时,只是有一点点不同,于是想应该可以把其简化,最开始想到的就是用反射,方法名用String
来代替,调用的时候传递一个String
就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| public class GasComponent extends HashMap<String, Double> implements ComponentCal { private PropertyRepository propertyRepository;
@Inject public void setPropertyRepository(PropertyRepository propertyRepository) { this.propertyRepository = propertyRepository; }
private double getPropertySum(String methodName, double factor) throws NoSuchMethodException, SecurityException { Method method; method = Property.class.getMethod(methodName); return this.entrySet().stream().mapToDouble(item -> { try { return Double.parseDouble(method.invoke(propertyRepository.getByName(item.getKey())).toString()) * item.getValue(); } catch (NumberFormatException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return 0.0; }).sum() * factor; }
public double getDensity() { double sum = 0.0; try { sum = getPropertySum("getDensity", 0.01); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } return sum; }
public double getQd() { double sum = 0.0; try { sum = getPropertySum("getQd", 1.0); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } return sum; }
}
|
方法四
我去,看着反射方法里面的各种try-catch
好烦啊,正好前段时间在学习Java8 In Action
,于是想到了函数式编程里讲到的东东。试试吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class GasComponent extends HashMap<String, Double> implements ComponentCal {
private PropertyRepository propertyRepository;
@Inject public void setPropertyRepository(PropertyRepository propertyRepository) { this.propertyRepository = propertyRepository; }
@FunctionalInterface private interface Functional { double getProperty(Property property); }
private Functional fDensity = p->p.getDensity(); private Functional fQd = p->p.getQd(); private Functional fQg = p->p.getQg(); private Functional fL_O2 = p->p.getL_O2(); private Functional fC = p->p.getC(); private Functional fH = p->p.getH();
private double getPropertySum(Functional f, double factor) { return this.entrySet().stream().mapToDouble(item -> f.getProperty(propertyRepository.getByName(item.getKey())) * item.getValue()).sum() * factor; }
public double getDensity() { return getPropertySum(fDensity, 0.01); }
public double getQd() { return getPropertySum(fQd, 1.0); }
}
|
哈哈哈,各种清爽啊。发现其实可以直接把labmda
表达式用参数形式传过去嘛。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class GasComponent extends HashMap<String, Double> implements ComponentCal {
private PropertyRepository propertyRepository;
@Inject public void setPropertyRepository(PropertyRepository propertyRepository) { this.propertyRepository = propertyRepository; }
@FunctionalInterface private interface Functional { double getProperty(Property property); }
private double getPropertySum(Functional f, double factor) { return this.entrySet().stream().mapToDouble(item -> f.getProperty(propertyRepository.getByName(item.getKey())) * item.getValue()).sum() * factor; }
public double getDensity() { return getPropertySum(p -> p.getDensity(), 0.01); }
public double getQd() { return getPropertySum(p -> p.getQd(), 1.0); }
}
|
Yeah,搞定,终于清爽了。 :)