@Override
  public void evaluateGroupBatch(VectorizedRowBatch batch)
      throws HiveException {

    evaluateInputExpr(batch);

    // Last row of last batch determines isGroupResultNull and long lastValue.

    // We do not filter when PTF is in reducer.
    Preconditions.checkState(!batch.selectedInUse);

    final int size = batch.size;
    if (size == 0) {
      return;
    }
    LongColumnVector longColVector = ((LongColumnVector) batch.cols[inputColumnNum]);
    if (longColVector.isRepeating) {

      if (longColVector.noNulls || !longColVector.isNull[0]) {
        lastValue = longColVector.vector[0];
        isGroupResultNull = false;
      } else {
        isGroupResultNull = true;
      }
    } else if (longColVector.noNulls) {
      lastValue = longColVector.vector[size - 1];
      isGroupResultNull = false;
    } else {
      final int lastBatchIndex = size - 1;
      if (!longColVector.isNull[lastBatchIndex]) {
        lastValue = longColVector.vector[lastBatchIndex];
        isGroupResultNull = false;
      } else {
        isGroupResultNull = true;
      }
    }
  }
This class evaluates long first_value() for a PTF group.

We capture the last value from the last batch.  It can be NULL.
It becomes the group value.
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/ptf/VectorPTFEvaluatorLongLastValue.java