Java 在ApacheDerby中创建用户定义的聚合函数

Java 在ApacheDerby中创建用户定义的聚合函数,java,derby,Java,Derby,我需要在Derby中创建一个用户定义的聚合(UDA)函数(特别是Variance函数),但我仍然坚持正确的编写方法 到目前为止,我有UDA的“模板”: public class Variance<V extends Comparable<V>> implements Aggregator<V,V,Variance<V>> { private ArrayList<V> _values; public Variance()

我需要在Derby中创建一个用户定义的聚合(UDA)函数(特别是
Variance
函数),但我仍然坚持正确的编写方法

到目前为止,我有UDA的“模板”:

public class Variance<V extends Comparable<V>> implements Aggregator<V,V,Variance<V>> {
    private ArrayList<V> _values;
    public Variance() {/*Empty constructor*/}
    public void init() {_values = new ArrayList<V>(); }
    public void accumulate(V v) { _values.add(v); }
    public void merge(Variance<V> o) { _values.addAll(o._values); }
    public V terminate() {
        // Here is my issue!!!
    }
}
公共类实现聚合器{
私有ArrayList_值;
公共方差(){/*空构造函数*/}
public void init(){u values=new ArrayList();}
公共void累积(V){_value.add(V);}
公共void合并(方差o){_值.addAll(o._值);}
公共V终止(){
//这是我的问题!!!
}
}
我面临的问题是:要计算方差,我需要计算如下:

V sum, sumSq;
int n = _values.size();
if(n <= 0)
    return null;
// Initialize sum and sumSq to "zero"
for(V v : _values) {
    sum += v; // Or somehow add v to sum
    sumSq += Math.pow(v, 2); // Or somehow add (v^2) to sumSq
}
return (sumSq - n * Math.pow(sum / n, 2)) / n;
V和,sumSq;
int n=_values.size();

如果(n查看Derby的数据类型:

DECIMAL = java.math.BigDecimal
INTEGER = java.lang.Integer
FLOAT = java.lang.Float or java.lang.Double 
FLOAT将根据创建时指定的精度转换为不同的Java对象,默认值为Java.lang.Double

添加数字

您遇到的第一个问题是简单地将值相加(对于二进制运算符“+”错误,有很多错误的操作数类型)。此外,即使您可以使用Integer、Float和Double,您也会发现,由于BigDecimal不直接映射到Java原语,因此它不能与标准原语算术运算符一起工作,并且因此在对象上有自己的add方法

引用

有很多方法可以一起解决,但老实说, 泛型并不是解决这个问题的方法。为每个泛型建立一个方法 具体的原始包装器类型并分别实现它们 算术是一个非常头痛的问题,不能使它通用 操作不能一般发生

平方值

第二个问题是,您使用的是power方法

Math.pow()适用于双参数-因此整数或双精度计算应该可以。Float可能会显示意外的结果,因为将Float转换为double可能会导致转换值中出现奇怪的额外数字

Math.pow的结果类型是Double,您可以通过定义聚合器来解决此问题,以便terminate方法结果类型始终是Double,例如:

public class Variance<V extends Number & Comparable<V>> 
    implements Aggregator<V, Double, Variance<V>> {
公共类变量
实现聚合器{
正如我们前面所看到的,BigDecimal与其他方法略有不同,它有自己的pow()方法,其结果类型是BigDecimal值

结论

鉴于上述情况,我建议不要尝试通用解决方案,而是为您想要支持的每种类类型实现多个方差聚合器。例如,您可以实现如下内容:

Aggregator<Integer, Double, Variance<Integer>>
Aggregator<Double, Double, Variance<Double>>
Aggregator<Float, Double, Variance<Float>>
Aggregator<BigDecimal, BigDecimal, Variance<BigDecimal>>  
聚合器
聚合器
聚合器
聚合器
//这不是最好的答案,但很有效
导入org.apache.derby.agg.Aggregator;
导入java.util.ArrayList;
公共类聚合器{
private ArrayList list=null;
公共方差(){}
公共void init(){
列表=新的ArrayList();
}
公共空间累积(V值){
列表。添加(值);
}
公共无效合并(另一个){
list.addAll(另一个.list);
}
公共V终止(){
双和=0,sumSq=0;
int n=list.size();

如果有什么解释就好了!
//that is not the best answer, but works 
            import org.apache.derby.agg.Aggregator; 
            import java.util.ArrayList;

            public class Variance<V extends Double> implements Aggregator<V,V,Variance<V>> {
              private ArrayList<V> list =null; 

               public Variance() {}

               public void init() {
                 list= new ArrayList<>(); 
               }

               public void accumulate(V value) {
                 list.add(value); 
               }

               public void merge(Variance<V> another) {
                 list.addAll(another.list); 
               }

               public V terminate() {
                 double sum=0, sumSq=0;
            int n = list.size();
            if(n <= 0)
                return null;
            // Initialize sum and sumSq to "zero"
            for(Double v : list) {
                sum += v; // Or somehow add v to sum
                sumSq += Math.pow(v, 2); // Or somehow add (v^2) to sumSq
            }
            return (V)(new Double((sumSq - n * Math.pow(sum / n, 2)) / n) ) ;
               }



                public static void main(String [] args) {
                  Variance<Double> v= new Variance<>(); 
                    v.init(); 
                    v.accumulate(new Double(8.0)); 
                     v.accumulate(new Double(6.0)); 
                     v.accumulate(new Double(10.0)); 

                     System.out.println(v.terminate()); 
                }
            }