@Override
    public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {
      assert (parameters.length == 3 || parameters.length == 4);
      if(parameters[0] == null || parameters[1] == null || parameters[2] == null) {
        return;
      }
      NGramAggBuf myagg = (NGramAggBuf) agg;

      // Parse out the context and 'k' if we haven't already done so, and while we're at it,
      // also parse out the precision factor 'pf' if the user has supplied one.
      if(!myagg.nge.isInitialized()) {
        int k = PrimitiveObjectInspectorUtils.getInt(parameters[2], kOI);
        int pf = 0;
        if(k < 1) {
          throw new HiveException(getClass().getSimpleName() + " needs 'k' to be at least 1, "
                                  + "but you supplied " + k);
        }
        if(parameters.length == 4) {
          pf = PrimitiveObjectInspectorUtils.getInt(parameters[3], pOI);
          if(pf < 1) {
            throw new HiveException(getClass().getSimpleName() + " needs 'pf' to be at least 1, "
                + "but you supplied " + pf);
          }
        } else {
          pf = 1; // placeholder; minimum pf value is enforced in NGramEstimator
        }

        // Parse out the context and make sure it isn't empty
        myagg.context.clear();
        List<Text> context = (List<Text>) contextListOI.getList(parameters[1]);
        int contextNulls = 0;
        for(int i = 0; i < context.size(); i++) {
          String word = PrimitiveObjectInspectorUtils.getString(context.get(i), contextOI);
          if(word == null) {
            contextNulls++;
          }
          myagg.context.add(word);
        }
        if(context.size() == 0) {
          throw new HiveException(getClass().getSimpleName() + " needs a context array " +
            "with at least one element.");
        }
        if(contextNulls == 0) {
          throw new HiveException(getClass().getSimpleName() + " the context array needs to " +
            "contain at least one 'null' value to indicate what should be counted.");
        }

        // Set parameters in the n-gram estimator object
        myagg.nge.initialize(k, pf, contextNulls);
      }

      // get the input expression
      List<Text> outer = (List<Text>) outerInputOI.getList(parameters[0]);
      if(innerInputOI != null) {
        // we're dealing with an array of arrays of strings
        for(int i = 0; i < outer.size(); i++) {
          List<Text> inner = (List<Text>) innerInputOI.getList(outer.get(i));
          ArrayList<String> words = new ArrayList<String>();
          for(int j = 0; j < inner.size(); j++) {
            String word = PrimitiveObjectInspectorUtils.getString(inner.get(j), inputOI);
            words.add(word);
          }

          // parse out n-grams, update frequency counts
          processNgrams(myagg, words);
        }
      } else {
        // we're dealing with an array of strings
        ArrayList<String> words = new ArrayList<String>();
        for(int i = 0; i < outer.size(); i++) {
          String word = PrimitiveObjectInspectorUtils.getString(outer.get(i), inputOI);
          words.add(word);
        }

        // parse out n-grams, update frequency counts
        processNgrams(myagg, words);
      }
    }
A constant-space heuristic to estimate the top-k contextual n-grams.
ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDAFContextNGrams.java