Aggregator的通用实现

时间:2013-03-31 06:10:16

标签: java generics aggregation

我正在创建一个CommonAggregator类,它可以聚合任何可聚合的对象。

public interface Aggregatable<T> {
    public void addFieldValue(T t, AggregationField<T> field);
}

public class Charges implements Aggregatable<Charges>{

//privat fields
//Getter and Setters

    @Override
    public void addFieldValue(Charges Charges, AggregationField<Charges> field){
        if(ChargeDetailAggregationField.TYPE1 == field){
            Type1 += Charges.getType1();
        }else if(ChargeDetailAggregationField.TYPE2 ==  field){
            Type2 += Charges.getType2();
        }else if(ChargeDetailAggregationField.TYPE3 == field){
            Type3 += Charges.getType3();
        }
    }
}

public class CommonAggregator<T extends Aggregatable<T>> {

    private static enum AggregationOperation {
        SUM, MAX, MIN, AVG;
    }

    private AggregationField<T>[] fieldsForSum;
    private AggregationField<T>[] fieldsForMax;
    private AggregationField<T>[] fieldsForMin;
    //private AggregationField groupByField = null;

    public CommonAggregator<T> sum(AggregationField<T>... fields){
        this.fieldsForSum = fields;
        return this;
    }

    public CommonAggregator<T> max(AggregationField<T>... fields){
        this.fieldsForMax = fields;
        return this;
    }

    public CommonAggregator<T> min(AggregationField<T>... fields){
        this.fieldsForMin = fields;
        return this;
    }

    private <T> void performOperation(AggregationOperation op,AggregatedResponse<T> aggregatedDetails,List<T> aggregatables,AggregationField<T>... fields){
        Aggregatable<T> aggregatedResponse = (Aggregatable<T>) getNewInstance();
        T response = null;
        for(AggregationField<T> field:fields){

            if(op == AggregationOperation.MAX){
                response = max(field,aggregatables);//Compilation Err
            }else if(op == AggregationOperation.MIN){
                response = min(field,aggregatables);//Compilation Err
            }else if(op == AggregationOperation.SUM){
                response = sum(field,aggregatables);//Compilation Err
            }

            aggregatedResponse.setFieldValue(response, field);

            if(op == AggregationOperation.MAX){
                aggregatedDetails.setMax(aggregatedResponse);
            }else if(op == AggregationOperation.MIN){
                aggregatedDetails.setMin(aggregatedResponse);
            }else if(op == AggregationOperation.SUM){
                aggregatedDetails.setSum(aggregatedResponse);
            }
        }
    }

    private T max(AggregationField<T> field,List<T> aggregatables){
        CommonComparator<T> comparator = new CommonComparator<T>(SortOrder.ASCENDING, field);
        return Collections.max(aggregatables, comparator);
    }

    private T min(AggregationField<T> field,List<T> aggregatables){
        CommonComparator<T> comparator = new CommonComparator<T>(SortOrder.ASCENDING, field);
        return Collections.min(aggregatables, comparator);
    }

    private T sum(AggregationField<T> field,List<T> listOfAggregatables){
        T aggregatable = listOfAggregatables.get(0);

        for(T response :listOfAggregatables.subList(1, listOfAggregatables.size())){
            aggregatable.addFieldValue(response, field);
        }
        return aggregatable;
    }

    public AggregatedResponse<T> aggregate(List<T> aggregatables){

        AggregatedResponse<T> aggregatedDetails = new AggregatedResponse<T>();
        if(fieldsForMax != null)
            performOperation(AggregationOperation.MAX,aggregatedDetails,aggregatables,fieldsForMax);
        if(fieldsForMin != null)
            performOperation(AggregationOperation.MIN,aggregatedDetails,aggregatables,fieldsForMin);
        if(fieldsForSum != null)
            performOperation(AggregationOperation.SUM,aggregatedDetails,aggregatables,fieldsForSum);

        return aggregatedDetails;
    }

    public <E> Map<E,List<T>> groupBy(AggregationField<T> fieldName, List<T> listOfAggregatable){
        Map<E,List<T>> groupedList = new HashMap<E,List<T>>();

        for(T t:listOfAggregatable){
            List<T> subList = null;

            E fieldValue = (E)t.getFieldValue(fieldName);
            if((subList = groupedList.get(fieldValue)) != null){
                subList.add(t);
            }else{
                subList = new ArrayList<T>();
                subList.add(t);
                groupedList.put(fieldValue,subList);
            }
        }

        return groupedList;
    }

    public <E> Map<E,AggregatedResponse<T>> groupByWithAggregation(AggregationField<T> fieldName, List<T> listOfAggregatable){
        //groupByField = fieldName;
        Map<E, List<T>> groupedByList = groupBy(fieldName, listOfAggregatable);
        Map<E,AggregatedResponse<T>> mapOfAggregatedDetails = new HashMap<E, AggregatedResponse<T>>();
        for(E key : groupedByList.keySet()){
            mapOfAggregatedDetails.put(key, aggregate(groupedByList.get(key)));
        }
        return mapOfAggregatedDetails;
    }

    :
}

这不是完整的代码。

这里,AggregationField告诉必须聚合哪个Aggregatable类字段。

问题

在performOperation()中调用max(),min()和sum()时,我遇到了followinf错误

CommonAggregator&lt;类型的方法max(AggregationField&lt; T&gt;,List&lt; T&gt;) T&GT;不适用于参数(AggregationField&lt; T&gt;,List&lt; T&gt;)

编辑:我在@Mikhail建议之后修改了原始代码和问题。

我对泛型不太了解。我想我只是在泛型中做错了。

1 个答案:

答案 0 :(得分:0)

public interface AggregationField <T>
{
    // ...
}

public interface Aggregatable <T>
{
    public void addFieldValue (T t, AggregationField <T> field);
}

public class Charges implements Aggregatable <Charges>
{
    @Override
    public void addFieldValue (
        Charges Charges, AggregationField <Charges> field)
    {
        // ...
    }
}

public class CommonAggregator <T extends Aggregatable <T>> {
    private T sum (
        AggregationField <T> field,
        List <? extends T> listOfAggregatables)
    {
        T aggregatable = listOfAggregatables.get(0);

        for (T response: listOfAggregatables.subList (1, listOfAggregatables.size())){
            aggregatable.addFieldValue(response, field);
        }

        return aggregatable;
    }
}