title: Generic implementation of Aggregator
body: <p>I am creating a class CommonAggregator which can aggregate any object which is Aggregatable.</p>
  
  <pre><code>public interface Aggregatable&lt;T&gt; {
      public void addFieldValue(T t, AggregationField&lt;T&gt; field);
  }
  
  public class Charges implements Aggregatable&lt;Charges&gt;{
  
  //privat fields
  //Getter and Setters
  
      @Override
      public void addFieldValue(Charges Charges, AggregationField&lt;Charges&gt; 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&lt;T extends Aggregatable&lt;T&gt;&gt; {
  
      private static enum AggregationOperation {
          SUM, MAX, MIN, AVG;
      }
  
      private AggregationField&lt;T&gt;[] fieldsForSum;
      private AggregationField&lt;T&gt;[] fieldsForMax;
      private AggregationField&lt;T&gt;[] fieldsForMin;
      //private AggregationField groupByField = null;
  
      public CommonAggregator&lt;T&gt; sum(AggregationField&lt;T&gt;... fields){
          this.fieldsForSum = fields;
          return this;
      }
  
      public CommonAggregator&lt;T&gt; max(AggregationField&lt;T&gt;... fields){
          this.fieldsForMax = fields;
          return this;
      }
  
      public CommonAggregator&lt;T&gt; min(AggregationField&lt;T&gt;... fields){
          this.fieldsForMin = fields;
          return this;
      }
  
      private &lt;T&gt; void performOperation(AggregationOperation op,AggregatedResponse&lt;T&gt; aggregatedDetails,List&lt;T&gt; aggregatables,AggregationField&lt;T&gt;... fields){
          Aggregatable&lt;T&gt; aggregatedResponse = (Aggregatable&lt;T&gt;) getNewInstance();
          T response = null;
          for(AggregationField&lt;T&gt; 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&lt;T&gt; field,List&lt;T&gt; aggregatables){
          CommonComparator&lt;T&gt; comparator = new CommonComparator&lt;T&gt;(SortOrder.ASCENDING, field);
          return Collections.max(aggregatables, comparator);
      }
  
      private T min(AggregationField&lt;T&gt; field,List&lt;T&gt; aggregatables){
          CommonComparator&lt;T&gt; comparator = new CommonComparator&lt;T&gt;(SortOrder.ASCENDING, field);
          return Collections.min(aggregatables, comparator);
      }
  
      private T sum(AggregationField&lt;T&gt; field,List&lt;T&gt; listOfAggregatables){
          T aggregatable = listOfAggregatables.get(0);
  
          for(T response :listOfAggregatables.subList(1, listOfAggregatables.size())){
              aggregatable.addFieldValue(response, field);
          }
          return aggregatable;
      }
  
      public AggregatedResponse&lt;T&gt; aggregate(List&lt;T&gt; aggregatables){
  
          AggregatedResponse&lt;T&gt; aggregatedDetails = new AggregatedResponse&lt;T&gt;();
          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 &lt;E&gt; Map&lt;E,List&lt;T&gt;&gt; groupBy(AggregationField&lt;T&gt; fieldName, List&lt;T&gt; listOfAggregatable){
          Map&lt;E,List&lt;T&gt;&gt; groupedList = new HashMap&lt;E,List&lt;T&gt;&gt;();
  
          for(T t:listOfAggregatable){
              List&lt;T&gt; subList = null;
  
              E fieldValue = (E)t.getFieldValue(fieldName);
              if((subList = groupedList.get(fieldValue)) != null){
                  subList.add(t);
              }else{
                  subList = new ArrayList&lt;T&gt;();
                  subList.add(t);
                  groupedList.put(fieldValue,subList);
              }
          }
  
          return groupedList;
      }
  
      public &lt;E&gt; Map&lt;E,AggregatedResponse&lt;T&gt;&gt; groupByWithAggregation(AggregationField&lt;T&gt; fieldName, List&lt;T&gt; listOfAggregatable){
          //groupByField = fieldName;
          Map&lt;E, List&lt;T&gt;&gt; groupedByList = groupBy(fieldName, listOfAggregatable);
          Map&lt;E,AggregatedResponse&lt;T&gt;&gt; mapOfAggregatedDetails = new HashMap&lt;E, AggregatedResponse&lt;T&gt;&gt;();
          for(E key : groupedByList.keySet()){
              mapOfAggregatedDetails.put(key, aggregate(groupedByList.get(key)));
          }
          return mapOfAggregatedDetails;
      }
  
      :
  }
  </code></pre>
  
  <p>This is not the complete code.</p>
  
  <p>Here, AggregationField tells which field of Aggregatable class has to be aggregated.</p>
  
  <p><strong>Problem</strong>:</p>
  
  <p>I have facing followinf error when calling max(), min(), and sum() in performOperation()</p>
  
  <p>The method max(AggregationField&lt; T>, List&lt; T>) in the type CommonAggregator&lt; T> is not applicable for the arguments (AggregationField&lt; T>, List&lt; T>)</p>
  
  <p>Edit: I have modified the original code and question after @Mikhail suggestion.</p>
  
  <p>I am not good in generics. And I guess I am doing something wrong in generics only.</p>