You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ab...@apache.org on 2020/05/14 11:30:48 UTC

[lucene-solr] branch jira/solr-14470 updated: SOLR-14470: Reduce object allocations. Add more efficient Tuple constructors.

This is an automated email from the ASF dual-hosted git repository.

ab pushed a commit to branch jira/solr-14470
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/jira/solr-14470 by this push:
     new ef66865  SOLR-14470: Reduce object allocations. Add more efficient Tuple constructors.
ef66865 is described below

commit ef66865c2f181bd913c24014b82107af1bd2532a
Author: Andrzej Bialecki <ab...@apache.org>
AuthorDate: Thu May 14 13:29:58 2020 +0200

    SOLR-14470: Reduce object allocations. Add more efficient Tuple constructors.
---
 .../java/org/apache/solr/handler/CatStream.java    | 19 +++++---------
 .../java/org/apache/solr/handler/GraphHandler.java | 10 +++-----
 .../java/org/apache/solr/handler/SQLHandler.java   | 10 ++++----
 .../org/apache/solr/handler/sql/LimitStream.java   |  6 +----
 .../src/test/org/apache/solr/core/HelloStream.java | 10 ++------
 .../org/apache/solr/client/solrj/io/Tuple.java     | 29 +++++++++++++++------
 .../solr/client/solrj/io/eval/AnovaEvaluator.java  | 11 ++++----
 .../solrj/io/eval/ChiSquareDataSetEvaluator.java   | 11 ++++----
 .../client/solrj/io/eval/DescribeEvaluator.java    | 30 ++++++++++------------
 .../solrj/io/eval/FrequencyTableEvaluator.java     | 16 +++++-------
 .../solrj/io/eval/GTestDataSetEvaluator.java       |  9 ++++---
 .../client/solrj/io/eval/HistogramEvaluator.java   | 24 ++++++++---------
 .../solrj/io/eval/KolmogorovSmirnovEvaluator.java  | 19 +++++++-------
 .../solrj/io/eval/MannWhitneyUEvaluator.java       | 11 ++++----
 .../client/solrj/io/eval/OutliersEvaluator.java    |  3 +--
 .../client/solrj/io/eval/PairedTTestEvaluator.java |  8 +++---
 .../client/solrj/io/eval/RecursiveEvaluator.java   |  8 +++---
 .../client/solrj/io/eval/SetValueEvaluator.java    |  8 +++---
 .../solr/client/solrj/io/eval/TTestEvaluator.java  | 10 +++-----
 .../client/solrj/io/graph/GatherNodesStream.java   | 13 +++-------
 .../apache/solr/client/solrj/io/graph/Node.java    | 16 ++++++------
 .../client/solrj/io/graph/ShortestPathStream.java  | 10 +++-----
 .../solr/client/solrj/io/ops/GroupOperation.java   |  7 +++--
 .../client/solrj/io/stream/CalculatorStream.java   | 12 +++------
 .../solr/client/solrj/io/stream/CellStream.java    |  7 ++---
 .../client/solrj/io/stream/CloudSolrStream.java    |  9 +++----
 .../solr/client/solrj/io/stream/CsvStream.java     |  3 +--
 .../solr/client/solrj/io/stream/DaemonStream.java  | 10 +++-----
 .../client/solrj/io/stream/DeepRandomStream.java   |  9 +++----
 .../solr/client/solrj/io/stream/EchoStream.java    | 11 ++------
 .../client/solrj/io/stream/ExceptionStream.java    | 10 ++------
 .../solr/client/solrj/io/stream/Facet2DStream.java | 11 +++-----
 .../solr/client/solrj/io/stream/FacetStream.java   | 12 +++------
 .../solrj/io/stream/FeaturesSelectionStream.java   | 20 +++++++--------
 .../solr/client/solrj/io/stream/GetStream.java     | 10 +++-----
 .../client/solrj/io/stream/HashRollupStream.java   |  8 +++---
 .../solr/client/solrj/io/stream/JDBCStream.java    | 23 ++++++++---------
 .../solr/client/solrj/io/stream/KnnStream.java     | 11 +++-----
 .../solr/client/solrj/io/stream/ListStream.java    |  5 +---
 .../solr/client/solrj/io/stream/ModelStream.java   |  4 +--
 .../solr/client/solrj/io/stream/NoOpStream.java    |  6 +----
 .../solr/client/solrj/io/stream/NullStream.java    |  3 +--
 .../client/solrj/io/stream/ParallelListStream.java |  7 ++---
 .../client/solrj/io/stream/ParallelStream.java     |  8 +-----
 .../solr/client/solrj/io/stream/PlotStream.java    |  6 ++---
 .../solr/client/solrj/io/stream/RandomStream.java  | 13 ++++------
 .../solr/client/solrj/io/stream/RollupStream.java  |  7 +++--
 .../client/solrj/io/stream/ScoreNodesStream.java   |  4 +--
 .../solr/client/solrj/io/stream/SearchStream.java  | 13 +++-------
 .../solr/client/solrj/io/stream/SelectStream.java  |  4 +--
 .../solrj/io/stream/SignificantTermsStream.java    |  4 +--
 .../solr/client/solrj/io/stream/SolrStream.java    |  4 +--
 .../solr/client/solrj/io/stream/StatsStream.java   | 22 +++++++---------
 .../client/solrj/io/stream/TextLogitStream.java    | 27 +++++++++----------
 .../client/solrj/io/stream/TimeSeriesStream.java   |  7 ++---
 .../solr/client/solrj/io/stream/TupStream.java     |  8 ++----
 .../solr/client/solrj/io/stream/UpdateStream.java  | 14 +++++-----
 .../solr/client/solrj/io/stream/ZplotStream.java   | 18 ++++++-------
 .../apache/solr/common/params/StreamParams.java    |  6 ++++-
 59 files changed, 257 insertions(+), 397 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/CatStream.java b/solr/core/src/java/org/apache/solr/handler/CatStream.java
index d1ebf5a..fa8140a 100644
--- a/solr/core/src/java/org/apache/solr/handler/CatStream.java
+++ b/solr/core/src/java/org/apache/solr/handler/CatStream.java
@@ -24,7 +24,6 @@ import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 
@@ -126,14 +125,14 @@ public class CatStream extends TupleStream implements Expressible {
   public Tuple read() throws IOException {
     if (maxLines >= 0 && linesReturned >= maxLines) {
       closeCurrentFileIfSet();
-      return createEofTuple();
+      return Tuple.EOF();
     } else if (currentFileHasMoreLinesToRead()) {
       return fetchNextLineFromCurrentFile();
     } else if (advanceToNextFileWithData()) {
       return fetchNextLineFromCurrentFile();
     } else { // No more data
       closeCurrentFileIfSet();
-      return createEofTuple();
+      return Tuple.EOF();
     }
   }
 
@@ -200,16 +199,10 @@ public class CatStream extends TupleStream implements Expressible {
   private Tuple fetchNextLineFromCurrentFile() {
     linesReturned++;
 
-    HashMap m = new HashMap();
-    m.put("file", currentFilePath.displayPath);
-    m.put("line", currentFileLines.next());
-    return new Tuple(m);
-  }
-
-  private Tuple createEofTuple() {
-    HashMap m = new HashMap();
-    m.put("EOF", true);
-    return new Tuple(m);
+    return new Tuple(
+        "file", currentFilePath.displayPath,
+        "line", currentFileLines.next()
+    );
   }
 
   private boolean currentFileHasMoreLinesToRead() {
diff --git a/solr/core/src/java/org/apache/solr/handler/GraphHandler.java b/solr/core/src/java/org/apache/solr/handler/GraphHandler.java
index 22c082f..42e8985 100644
--- a/solr/core/src/java/org/apache/solr/handler/GraphHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/GraphHandler.java
@@ -20,7 +20,6 @@ package org.apache.solr.handler;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -40,6 +39,7 @@ import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.params.StreamParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.PluginInfo;
@@ -202,11 +202,7 @@ public class GraphHandler extends RequestHandlerBase implements SolrCoreAware, P
     }
 
     public Tuple read() {
-      String msg = e.getMessage();
-      Map m = new HashMap();
-      m.put("EOF", true);
-      m.put("EXCEPTION", msg);
-      return new Tuple(m);
+      return Tuple.EXCEPTION(e.getMessage(), true);
     }
   }
 
@@ -257,7 +253,7 @@ public class GraphHandler extends RequestHandlerBase implements SolrCoreAware, P
       Tuple tuple = this.tupleStream.read();
       if(tuple.EOF) {
         long totalTime = (System.nanoTime() - begin) / 1000000;
-        tuple.fields.put("RESPONSE_TIME", totalTime);
+        tuple.fields.put(StreamParams.RESPONSE_TIME, totalTime);
       }
       return tuple;
     }
diff --git a/solr/core/src/java/org/apache/solr/handler/SQLHandler.java b/solr/core/src/java/org/apache/solr/handler/SQLHandler.java
index 6b0330a..8bc1491 100644
--- a/solr/core/src/java/org/apache/solr/handler/SQLHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SQLHandler.java
@@ -159,7 +159,7 @@ public class SQLHandler extends RequestHandlerBase implements SolrCoreAware, Per
       // Return a metadata tuple as the first tuple and then pass through to the JDBCStream.
       if(firstTuple) {
         try {
-          Map<String, Object> fields = new HashMap<>();
+          Tuple tuple = new Tuple();
 
           firstTuple = false;
 
@@ -173,10 +173,10 @@ public class SQLHandler extends RequestHandlerBase implements SolrCoreAware, Per
           }
 
           if(includeMetadata) {
-            fields.put("isMetadata", true);
-            fields.put("fields", metadataFields);
-            fields.put("aliases", metadataAliases);
-            return new Tuple(fields);
+            tuple.put("isMetadata", true);
+            tuple.put("fields", metadataFields);
+            tuple.put("aliases", metadataAliases);
+            return tuple;
           }
         } catch (SQLException e) {
           throw new IOException(e);
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java b/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
index 0d4bb72..772f639 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/LimitStream.java
@@ -26,9 +26,7 @@ import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 class LimitStream extends TupleStream {
 
@@ -79,9 +77,7 @@ class LimitStream extends TupleStream {
   public Tuple read() throws IOException {
     ++count;
     if(count > limit) {
-      Map<String, String> fields = new HashMap<>();
-      fields.put("EOF", "true");
-      return new Tuple(fields);
+      return Tuple.EOF();
     }
 
     return stream.read();
diff --git a/solr/core/src/test/org/apache/solr/core/HelloStream.java b/solr/core/src/test/org/apache/solr/core/HelloStream.java
index be285e5..3702005 100644
--- a/solr/core/src/test/org/apache/solr/core/HelloStream.java
+++ b/solr/core/src/test/org/apache/solr/core/HelloStream.java
@@ -18,9 +18,7 @@
 package org.apache.solr.core;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.StreamComparator;
@@ -67,14 +65,10 @@ public class HelloStream extends TupleStream implements Expressible{
   @Override
   public Tuple read() throws IOException {
     if (isSentHelloWorld) {
-      Map m = new HashMap();
-      m.put("EOF", true);
-      return new Tuple(m);
+      return Tuple.EOF();
     } else {
       isSentHelloWorld = true;
-      Map m = new HashMap<>();
-      m.put("msg", "Hello World!");
-      return new Tuple(m);
+      return new Tuple("msg", "Hello World!");
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/Tuple.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/Tuple.java
index 39c6ad9..b6bcb11 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/Tuple.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/Tuple.java
@@ -23,7 +23,6 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 
 import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.params.StreamParams;
@@ -46,7 +45,7 @@ public class Tuple implements Cloneable, MapWriter {
   public boolean EOF;
   public boolean EXCEPTION;
 
-  public Map<Object, Object> fields = new HashMap<>();
+  public Map<Object, Object> fields = new HashMap<>(2);
   public List<String> fieldNames;
   public Map<String, String> fieldLabels;
 
@@ -60,8 +59,15 @@ public class Tuple implements Cloneable, MapWriter {
     }
   }
 
+  /**
+   * Constructor that accepts an even number of arguments as key / value pairs.
+   * @param fields a list of key / value pairs, with keys at odd and values at
+   *               even positions.
+   */
   public Tuple(Object... fields) {
-    Objects.requireNonNull(fields);
+    if (fields == null) {
+      return;
+    }
     if ((fields.length % 2) != 0) {
       throw new RuntimeException("must have a matching number of key-value pairs");
     }
@@ -81,9 +87,8 @@ public class Tuple implements Cloneable, MapWriter {
     } else if (key.equals(StreamParams.EXCEPTION)) {
       EXCEPTION = true;
     }
-
   }
-  
+
   public void remove(Object key) {
     this.fields.remove(key);
   }
@@ -233,17 +238,25 @@ public class Tuple implements Cloneable, MapWriter {
     }
   }
 
+  /**
+   * Create a new empty tuple marked as EOF.
+   */
   public static Tuple EOF() {
     Tuple tuple = new Tuple();
-    tuple.put((Object) StreamParams.EOF, true);
+    tuple.put(StreamParams.EOF, true);
     return tuple;
   }
 
+  /**
+   * Create a new empty tuple marked as EXCEPTION, and optionally EOF.
+   * @param msg exception message
+   * @param eof if true the tuple will be marked as EOF
+   */
   public static Tuple EXCEPTION(String msg, boolean eof) {
     Tuple tuple = new Tuple();
-    tuple.put((Object) StreamParams.EXCEPTION, msg);
+    tuple.put(StreamParams.EXCEPTION, msg);
     if (eof) {
-      tuple.put((Object) StreamParams.EOF, true);
+      tuple.put(StreamParams.EOF, true);
     }
     return tuple;
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
index 197e4e2..26464d1b 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/AnovaEvaluator.java
@@ -18,16 +18,15 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.apache.commons.math3.stat.inference.OneWayAnova;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 public class AnovaEvaluator extends RecursiveNumericListEvaluator implements ManyValueWorker {
   protected static final long serialVersionUID = 1L;
@@ -54,10 +53,10 @@ public class AnovaEvaluator extends RecursiveNumericListEvaluator implements Man
     OneWayAnova anova = new OneWayAnova();
     double p = anova.anovaPValue(anovaInput);
     double f = anova.anovaFValue(anovaInput);
-    Map<String,Number> m = new HashMap<>();
-    m.put("p-value", p);
-    m.put("f-ratio", f);
-    return new Tuple(m);
+    Tuple tuple = new Tuple();
+    tuple.put(StreamParams.P_VALUE, p);
+    tuple.put("f-ratio", f);
+    return tuple;
   }
   
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ChiSquareDataSetEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ChiSquareDataSetEvaluator.java
index 9eb963a..4c20b8c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ChiSquareDataSetEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/ChiSquareDataSetEvaluator.java
@@ -18,14 +18,13 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.commons.math3.stat.inference.ChiSquareTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 
 public class ChiSquareDataSetEvaluator extends RecursiveNumericListEvaluator implements TwoValueWorker {
@@ -56,10 +55,10 @@ public class ChiSquareDataSetEvaluator extends RecursiveNumericListEvaluator imp
     double chiSquare = chiSquareTest.chiSquareDataSetsComparison(sampleA, sampleB);
     double p = chiSquareTest.chiSquareTestDataSetsComparison(sampleA, sampleB);
 
-    Map<String,Number> m = new HashMap<>();
-    m.put("chisquare-statistic", chiSquare);
-    m.put("p-value", p);
-    return new Tuple(m);
+    Tuple tuple = new Tuple();
+    tuple.put("chisquare-statistic", chiSquare);
+    tuple.put(StreamParams.P_VALUE, p);
+    return tuple;
 
   }
 }
\ No newline at end of file
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
index 2fce7a0..27ef0de 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/DescribeEvaluator.java
@@ -17,10 +17,8 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
 import org.apache.solr.client.solrj.io.Tuple;
@@ -49,20 +47,20 @@ public class DescribeEvaluator extends RecursiveNumericEvaluator implements OneV
     DescriptiveStatistics descriptiveStatistics = new DescriptiveStatistics();
     ((List<?>)value).stream().mapToDouble(innerValue -> ((Number)innerValue).doubleValue()).forEach(innerValue -> descriptiveStatistics.addValue(innerValue));
 
-    Map<String,Number> map = new HashMap<>();
-    map.put("max", descriptiveStatistics.getMax());
-    map.put("mean", descriptiveStatistics.getMean());
-    map.put("min", descriptiveStatistics.getMin());
-    map.put("stdev", descriptiveStatistics.getStandardDeviation());
-    map.put("sum", descriptiveStatistics.getSum());
-    map.put("N", descriptiveStatistics.getN());
-    map.put("var", descriptiveStatistics.getVariance());
-    map.put("kurtosis", descriptiveStatistics.getKurtosis());
-    map.put("skewness", descriptiveStatistics.getSkewness());
-    map.put("popVar", descriptiveStatistics.getPopulationVariance());
-    map.put("geometricMean", descriptiveStatistics.getGeometricMean());
-    map.put("sumsq", descriptiveStatistics.getSumsq());
+    Tuple tuple = new Tuple();
+    tuple.put("max", descriptiveStatistics.getMax());
+    tuple.put("mean", descriptiveStatistics.getMean());
+    tuple.put("min", descriptiveStatistics.getMin());
+    tuple.put("stdev", descriptiveStatistics.getStandardDeviation());
+    tuple.put("sum", descriptiveStatistics.getSum());
+    tuple.put("N", descriptiveStatistics.getN());
+    tuple.put("var", descriptiveStatistics.getVariance());
+    tuple.put("kurtosis", descriptiveStatistics.getKurtosis());
+    tuple.put("skewness", descriptiveStatistics.getSkewness());
+    tuple.put("popVar", descriptiveStatistics.getPopulationVariance());
+    tuple.put("geometricMean", descriptiveStatistics.getGeometricMean());
+    tuple.put("sumsq", descriptiveStatistics.getSumsq());
 
-    return new Tuple(map);
+    return tuple;
   }  
 }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FrequencyTableEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FrequencyTableEvaluator.java
index b648e3f..a553520 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FrequencyTableEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/FrequencyTableEvaluator.java
@@ -19,11 +19,9 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.stat.Frequency;
 
@@ -71,13 +69,13 @@ public class FrequencyTableEvaluator extends RecursiveNumericEvaluator implement
 
     while(iterator.hasNext()){
       Long value = (Long)iterator.next();
-      Map<String,Number> map = new HashMap<>();
-      map.put("value", value.longValue());
-      map.put("count", frequency.getCount(value));
-      map.put("cumFreq", frequency.getCumFreq(value));
-      map.put("cumPct", frequency.getCumPct(value));
-      map.put("pct", frequency.getPct(value));
-      histogramBins.add(new Tuple(map));
+      Tuple tuple = new Tuple();
+      tuple.put("value", value.longValue());
+      tuple.put("count", frequency.getCount(value));
+      tuple.put("cumFreq", frequency.getCumFreq(value));
+      tuple.put("cumPct", frequency.getCumPct(value));
+      tuple.put("pct", frequency.getPct(value));
+      histogramBins.add(tuple);
     }
     return histogramBins;
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/GTestDataSetEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/GTestDataSetEvaluator.java
index d553197..591b519 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/GTestDataSetEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/GTestDataSetEvaluator.java
@@ -26,6 +26,7 @@ import org.apache.commons.math3.stat.inference.GTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 
 public class GTestDataSetEvaluator extends RecursiveNumericListEvaluator implements TwoValueWorker {
@@ -56,9 +57,9 @@ public class GTestDataSetEvaluator extends RecursiveNumericListEvaluator impleme
     double g = gTest.gDataSetsComparison(sampleA, sampleB);
     double p = gTest.gTestDataSetsComparison(sampleA, sampleB);
 
-    Map<String,Number> m = new HashMap<>();
-    m.put("G-statistic", g);
-    m.put("p-value", p);
-    return new Tuple(m);
+   Tuple tuple = new Tuple();
+    tuple.put("G-statistic", g);
+    tuple.put(StreamParams.P_VALUE, p);
+    return tuple;
   }
 }
\ No newline at end of file
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
index 8d27614..fd6fcf6 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/HistogramEvaluator.java
@@ -19,10 +19,8 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.random.EmpiricalDistribution;
 import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
@@ -71,17 +69,17 @@ public class HistogramEvaluator extends RecursiveNumericEvaluator implements Man
 
     List<Tuple> histogramBins = new ArrayList<>();
     for(SummaryStatistics binSummary : distribution.getBinStats()) {
-      Map<String,Number> map = new HashMap<>();
-      map.put("max", binSummary.getMax());
-      map.put("mean", binSummary.getMean());
-      map.put("min", binSummary.getMin());
-      map.put("stdev", binSummary.getStandardDeviation());
-      map.put("sum", binSummary.getSum());
-      map.put("N", binSummary.getN());
-      map.put("var", binSummary.getVariance());
-      map.put("cumProb", distribution.cumulativeProbability(binSummary.getMean()));
-      map.put("prob", distribution.probability(binSummary.getMin(), binSummary.getMax()));
-      histogramBins.add(new Tuple(map));
+      Tuple tuple = new Tuple();
+      tuple.put("max", binSummary.getMax());
+      tuple.put("mean", binSummary.getMean());
+      tuple.put("min", binSummary.getMin());
+      tuple.put("stdev", binSummary.getStandardDeviation());
+      tuple.put("sum", binSummary.getSum());
+      tuple.put("N", binSummary.getN());
+      tuple.put("var", binSummary.getVariance());
+      tuple.put("cumProb", distribution.cumulativeProbability(binSummary.getMean()));
+      tuple.put("prob", distribution.probability(binSummary.getMin(), binSummary.getMax()));
+      histogramBins.add(tuple);
     }
     
     return histogramBins;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/KolmogorovSmirnovEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/KolmogorovSmirnovEvaluator.java
index 58e783e..27256b1 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/KolmogorovSmirnovEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/KolmogorovSmirnovEvaluator.java
@@ -17,16 +17,15 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.distribution.RealDistribution;
 import org.apache.commons.math3.stat.inference.KolmogorovSmirnovTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 public class KolmogorovSmirnovEvaluator extends RecursiveObjectEvaluator implements TwoValueWorker {
 
@@ -54,17 +53,17 @@ public class KolmogorovSmirnovEvaluator extends RecursiveObjectEvaluator impleme
     if(first instanceof RealDistribution){
       RealDistribution realDistribution = (RealDistribution)first;
 
-      Map<String,Double> m = new HashMap<>();
-      m.put("p-value", ks.kolmogorovSmirnovTest(realDistribution, data));
-      m.put("d-statistic", ks.kolmogorovSmirnovStatistic(realDistribution, data));
-      return new Tuple(m);
+      Tuple tuple = new Tuple();
+      tuple.put(StreamParams.P_VALUE, ks.kolmogorovSmirnovTest(realDistribution, data));
+      tuple.put("d-statistic", ks.kolmogorovSmirnovStatistic(realDistribution, data));
+      return tuple;
     }
     else if(first instanceof List<?> && ((List<?>) first).stream().noneMatch(item -> !(item instanceof Number))){
       double[] data2 = ((List<?>)first).stream().mapToDouble(item -> ((Number)item).doubleValue()).toArray();
-      
-      Map<String,Double> m = new HashMap<>();
-      m.put("d-statistic", ks.kolmogorovSmirnovTest(data, data2));
-      return new Tuple(m);
+
+      Tuple tuple = new Tuple();
+      tuple.put("d-statistic", ks.kolmogorovSmirnovTest(data, data2));
+      return tuple;
     }
     else{
       throw new IOException(String.format(Locale.ROOT,"Invalid expression %s - found type %s for the first value, expecting a RealDistribution or list of numbers",toExpression(constructingFactory), first.getClass().getSimpleName()));
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MannWhitneyUEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MannWhitneyUEvaluator.java
index defa919..4da11e4 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MannWhitneyUEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/MannWhitneyUEvaluator.java
@@ -19,16 +19,15 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 import org.apache.commons.math3.stat.inference.MannWhitneyUTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 
 public class MannWhitneyUEvaluator extends RecursiveNumericListEvaluator implements ManyValueWorker {
@@ -51,10 +50,10 @@ public class MannWhitneyUEvaluator extends RecursiveNumericListEvaluator impleme
       MannWhitneyUTest mannwhitneyutest = new MannWhitneyUTest();
       double u = mannwhitneyutest.mannWhitneyU(mannWhitneyUInput.get(0), mannWhitneyUInput.get(1));
       double p = mannwhitneyutest.mannWhitneyUTest(mannWhitneyUInput.get(0), mannWhitneyUInput.get(1));
-      Map<String,Number> m = new HashMap<>();
-      m.put("u-statistic", u);
-      m.put("p-value", p);
-      return new Tuple(m);
+      Tuple tuple = new Tuple();
+      tuple.put("u-statistic", u);
+      tuple.put(StreamParams.P_VALUE, p);
+      return tuple;
     }else{
       throw new IOException(String.format(Locale.ROOT,"%s(...) only works with a list of 2 arrays but a list of %d array(s) was provided.", constructingFactory.getFunctionName(getClass()), mannWhitneyUInput.size()));
     }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/OutliersEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/OutliersEvaluator.java
index 5a14a52..4614d10 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/OutliersEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/OutliersEvaluator.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.commons.math3.distribution.IntegerDistribution;
@@ -76,7 +75,7 @@ public class OutliersEvaluator extends RecursiveObjectEvaluator implements ManyV
     } else {
       tuples = new ArrayList();
       for(int i=0; i<vec.size(); i++) {
-        tuples.add(new Tuple(new HashMap()));
+        tuples.add(new Tuple());
       }
     }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairedTTestEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairedTTestEvaluator.java
index 56c2dc9..ead985c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairedTTestEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/PairedTTestEvaluator.java
@@ -17,15 +17,14 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.stat.inference.TTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 public class PairedTTestEvaluator extends RecursiveNumericListEvaluator implements TwoValueWorker {
   protected static final long serialVersionUID = 1L;
@@ -42,8 +41,7 @@ public class PairedTTestEvaluator extends RecursiveNumericListEvaluator implemen
   public Object doWork(Object value1, Object value2) throws IOException {
 
     TTest tTest = new TTest();
-    Map map = new HashMap();
-    Tuple tuple = new Tuple(map);
+    Tuple tuple = new Tuple();
     if(value1 instanceof List) {
       List<Number> values1 = (List<Number>)value1;
       double[] samples1 = new double[values1.size()];
@@ -63,7 +61,7 @@ public class PairedTTestEvaluator extends RecursiveNumericListEvaluator implemen
         double tstat = tTest.pairedT(samples1, samples2);
         double pval = tTest.pairedTTest(samples1, samples2);
         tuple.put("t-statistic", tstat);
-        tuple.put("p-value", pval);
+        tuple.put(StreamParams.P_VALUE, pval);
         return tuple;
       } else {
         throw new IOException("Second parameter for pairedTtest must be a double array");
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RecursiveEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RecursiveEvaluator.java
index 97224dd..f474f43 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RecursiveEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/RecursiveEvaluator.java
@@ -22,8 +22,6 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
@@ -145,12 +143,12 @@ public abstract class RecursiveEvaluator implements StreamEvaluator, ValueWorker
       //can be contained within a tuple.
 
       Tuple tuple = (Tuple)value;
-      Map map = new HashMap();
+      Tuple newTuple = new Tuple();
       for(Object o : tuple.fields.keySet()) {
         Object v = tuple.fields.get(o);
-        map.put(o, normalizeOutputType(v));
+        newTuple.put(o, normalizeOutputType(v));
       }
-      return new Tuple(map);
+      return newTuple;
     }
     else{
       // anything else can just be returned as is
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SetValueEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SetValueEvaluator.java
index 8ded259..47ef0ec 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SetValueEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/SetValueEvaluator.java
@@ -19,8 +19,6 @@ package org.apache.solr.client.solrj.io.eval;
 import java.io.IOException;
 
 import java.util.Locale;
-import java.util.Map;
-import java.util.HashMap;
 
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
@@ -47,9 +45,9 @@ public class SetValueEvaluator extends RecursiveObjectEvaluator implements ManyV
         value = ((String)value).replace("\"", "");
       }
       key = key.replace("\"", "");
-      Map map = new HashMap(tuple.fields);
-      map.put(key, value);
-      return new Tuple(map);
+      Tuple newTuple = new Tuple(tuple.fields);
+      newTuple.put(key, value);
+      return newTuple;
     } else {
       throw new IOException("The setValue function expects a Tuple as the first parameter");
     }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/TTestEvaluator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/TTestEvaluator.java
index 6273376..ef66afd 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/TTestEvaluator.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/eval/TTestEvaluator.java
@@ -17,15 +17,14 @@
 package org.apache.solr.client.solrj.io.eval;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.commons.math3.stat.inference.TTest;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpression;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 public class TTestEvaluator extends RecursiveNumericEvaluator implements TwoValueWorker {
   protected static final long serialVersionUID = 1L;
@@ -42,8 +41,7 @@ public class TTestEvaluator extends RecursiveNumericEvaluator implements TwoValu
   public Object doWork(Object value1, Object value2) throws IOException {
 
     TTest tTest = new TTest();
-    Map map = new HashMap();
-    Tuple tuple = new Tuple(map);
+    Tuple tuple = new Tuple();
     if(value1 instanceof Number) {
       double mean = ((Number) value1).doubleValue();
 
@@ -58,7 +56,7 @@ public class TTestEvaluator extends RecursiveNumericEvaluator implements TwoValu
         double pval = tTest.tTest(mean, samples);
 
         tuple.put("t-statistic", tstat);
-        tuple.put("p-value", pval);
+        tuple.put(StreamParams.P_VALUE, pval);
         return tuple;
       } else {
         throw new IOException("Second parameter for ttest must be a double array");
@@ -83,7 +81,7 @@ public class TTestEvaluator extends RecursiveNumericEvaluator implements TwoValu
         double tstat = tTest.t(samples1, samples2);
         double pval = tTest.tTest(samples1, samples2);
         tuple.put("t-statistic", tstat);
-        tuple.put("p-value", pval);
+        tuple.put(StreamParams.P_VALUE, pval);
         return tuple;
       } else {
         throw new IOException("Second parameter for ttest must be a double array");
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
index 5796065..702d034 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/GatherNodesStream.java
@@ -613,10 +613,7 @@ public class GatherNodesStream extends TupleStream implements Expressible {
     if (out.hasNext()) {
       return out.next();
     } else {
-      Map map = new HashMap();
-      map.put("EOF", true);
-      Tuple tuple = new Tuple(map);
-      return tuple;
+      return Tuple.EOF();
     }
   }
 
@@ -645,14 +642,10 @@ public class GatherNodesStream extends TupleStream implements Expressible {
     public void setStreamContext(StreamContext context) {}
 
     public Tuple read() {
-      HashMap map = new HashMap();
       if(it.hasNext()) {
-        map.put("node",it.next());
-        return new Tuple(map);
+        return new Tuple("node",it.next());
       } else {
-
-        map.put("EOF", true);
-        return new Tuple(map);
+        return Tuple.EOF();
       }
     }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/Node.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/Node.java
index befa5a7..7c99f75 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/Node.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/Node.java
@@ -51,12 +51,12 @@ public class Node {
   }
 
   public Tuple toTuple(String collection, String field, int level, Traversal traversal) {
-    Map map = new HashMap();
+    Tuple tuple = new Tuple();
 
-    map.put("node", id);
-    map.put("collection", collection);
-    map.put("field", field);
-    map.put("level", level);
+    tuple.put("node", id);
+    tuple.put("collection", collection);
+    tuple.put("field", field);
+    tuple.put("level", level);
 
     boolean prependCollection = traversal.isMultiCollection();
     List<String> cols = traversal.getCollections();
@@ -76,15 +76,15 @@ public class Node {
         }
       }
 
-      map.put("ancestors", l);
+      tuple.put("ancestors", l);
     }
 
     if(metrics != null) {
       for(Metric metric : metrics) {
-        map.put(metric.getIdentifier(), metric.getValue());
+        tuple.put(metric.getIdentifier(), metric.getValue());
       }
     }
 
-    return new Tuple(map);
+    return tuple;
   }
 }
\ No newline at end of file
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/ShortestPathStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/ShortestPathStream.java
index 314ab92..9d12e48 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/ShortestPathStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/graph/ShortestPathStream.java
@@ -403,8 +403,7 @@ public class ShortestPathStream extends TupleStream implements Expressible {
         for(LinkedList p : paths) {
           String s = p.toString();
           if (!finalPaths.contains(s)){
-            Tuple shortestPath = new Tuple(new HashMap());
-            shortestPath.put("path", p);
+            Tuple shortestPath = new Tuple("path", p);
             shortestPaths.add(shortestPath);
             finalPaths.add(s);
           }
@@ -501,12 +500,11 @@ public class ShortestPathStream extends TupleStream implements Expressible {
       Tuple t = shortestPaths.removeFirst();
       return t;
     } else {
-      Map m = new HashMap();
-      m.put("EOF", true);
+      Tuple tuple = Tuple.EOF();
       if(!found) {
-        m.put("sorry", "No path found");
+        tuple.put("sorry", "No path found");
       }
-      return new Tuple(m);
+      return tuple;
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/ops/GroupOperation.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/ops/GroupOperation.java
index 3db76ec..bd3250e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/ops/GroupOperation.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/ops/GroupOperation.java
@@ -20,7 +20,6 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
@@ -114,9 +113,9 @@ public class GroupOperation implements ReduceOperation {
 
     List<Map> list = new ArrayList(ll);
     Map groupHead = list.get(0);
-    Map map = new HashMap(groupHead);
-    map.put("group", list);
-    return new Tuple(map);
+    Tuple tuple = new Tuple(groupHead);
+    tuple.put("group", list);
+    return tuple;
   }
 
   public void operate(Tuple tuple) {
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CalculatorStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CalculatorStream.java
index 49b5953..d2efbb2 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CalculatorStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CalculatorStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -86,16 +85,11 @@ public class CalculatorStream extends TupleStream implements Expressible {
 
   public Tuple read() throws IOException {
 
-    if(finished) {
-      HashMap m = new HashMap();
-      m.put("EOF", true);
-      Tuple tuple = new Tuple(m);
-      return tuple;
+    if (finished) {
+      return Tuple.EOF();
     } else {
-      HashMap m = new HashMap();
-      Tuple tuple = new Tuple(m);
       finished = true;
-      return tuple;
+      return new Tuple();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CellStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CellStream.java
index a87c9ee..fac8ca8 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CellStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CellStream.java
@@ -18,10 +18,8 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.StreamComparator;
@@ -134,9 +132,8 @@ public class CellStream extends TupleStream implements Expressible {
         }
       }
 
-      Map map = new HashMap();
-      map.put(name, list);
-      tuple = new Tuple(map);
+      tuple = new Tuple();
+      tuple.put(name, list);
     } finally {
       stream.close();
     }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
index 95cf239..dfa0211 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
@@ -453,14 +453,11 @@ public class CloudSolrStream extends TupleStream implements Expressible {
       }
       return t;
     } else {
-      Map m = new HashMap();
+      Tuple tuple = Tuple.EOF();
       if(trace) {
-        m.put("_COLLECTION_", this.collection);
+        tuple.put("_COLLECTION_", this.collection);
       }
-
-      m.put("EOF", true);
-
-      return new Tuple(m);
+      return tuple;
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CsvStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CsvStream.java
index 561204f..386cb5d 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CsvStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CsvStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 
@@ -130,7 +129,7 @@ public class CsvStream extends TupleStream implements Expressible {
         if(fields.length != headers.length) {
           throw new IOException("Headers and lines must have the same number of fields [file:"+file+" line number:"+lineNumber+"]");
         }
-        Tuple out = new Tuple(new HashMap());
+        Tuple out = new Tuple();
         out.put("id", file+"_"+lineNumber);
         for(int i=0; i<headers.length; i++) {
           if(fields[i] != null && fields[i].length() > 0) {
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DaemonStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DaemonStream.java
index 0257be9..0960bf7 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DaemonStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DaemonStream.java
@@ -21,7 +21,6 @@ import java.lang.Thread.State;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -252,13 +251,13 @@ public class DaemonStream extends TupleStream implements Expressible {
   }
 
   public synchronized Tuple getInfo() {
-    Tuple tuple = new Tuple(new HashMap());
+    Tuple tuple = new Tuple();
     tuple.put(ID, id);
     tuple.put("startTime", startTime);
     tuple.put("stopTime", stopTime);
     tuple.put("iterations", iterations.get());
     tuple.put("state", streamRunner.getState().toString());
-    if(exception != null) {
+    if (exception != null) {
       tuple.put("exception", exception.getMessage());
     }
 
@@ -400,11 +399,8 @@ public class DaemonStream extends TupleStream implements Expressible {
       }
 
       if(!eatTuples) {
-        Map m = new HashMap();
-        m.put("EOF", true);
-        Tuple tuple = new Tuple(m);
         try {
-          queue.put(tuple);
+          queue.put(Tuple.EOF());
         } catch (InterruptedException e) {
           log.error("Error in DaemonStream:{}", id, e);
         }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DeepRandomStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DeepRandomStream.java
index 9c9c201..1d53604 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DeepRandomStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/DeepRandomStream.java
@@ -403,14 +403,11 @@ public class DeepRandomStream extends TupleStream implements Expressible {
       }
       return t;
     } else {
-      Map m = new HashMap();
+      Tuple tuple = Tuple.EOF();
       if(trace) {
-        m.put("_COLLECTION_", this.collection);
+        tuple.put("_COLLECTION_", this.collection);
       }
-
-      m.put("EOF", true);
-
-      return new Tuple(m);
+      return tuple;
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/EchoStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/EchoStream.java
index 38e1cca..7749a0f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/EchoStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/EchoStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -96,16 +95,10 @@ public class EchoStream extends TupleStream implements Expressible {
   public Tuple read() throws IOException {
 
     if(finished) {
-      HashMap m = new HashMap();
-      m.put("EOF", true);
-      Tuple tuple = new Tuple(m);
-      return tuple;
+      return Tuple.EOF();
     } else {
-      HashMap m = new HashMap();
-      m.put("echo", echo);
-      Tuple tuple = new Tuple(m);
       finished = true;
-      return tuple;
+      return new Tuple("echo", echo);
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ExceptionStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ExceptionStream.java
index 9d1f450..39fb90c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ExceptionStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ExceptionStream.java
@@ -60,21 +60,15 @@ public class ExceptionStream extends TupleStream {
   public Tuple read() {
     if(openException != null) {
       //There was an exception during the open.
-      Map fields = new HashMap();
-      fields.put("EXCEPTION", openException.getMessage());
-      fields.put("EOF", true);
       SolrException.log(log, openException);
-      return new Tuple(fields);
+      return Tuple.EXCEPTION(openException.getMessage(), true);
     }
 
     try {
       return stream.read();
     } catch (Exception e) {
-      Map fields = new HashMap();
-      fields.put("EXCEPTION", e.getMessage());
-      fields.put("EOF", true);
       SolrException.log(log, e);
-      return new Tuple(fields);
+      return Tuple.EXCEPTION(e.getMessage(), true);
     }
   }
   
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/Facet2DStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/Facet2DStream.java
index 2ccb147..7f3d635 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/Facet2DStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/Facet2DStream.java
@@ -20,11 +20,9 @@ package org.apache.solr.client.solrj.io.stream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -308,11 +306,8 @@ public class Facet2DStream extends TupleStream implements Expressible {
     if (out.hasNext()) {
       return out.next();
     } else {
-      Map fields = new HashMap();
-      fields.put("rows", tuples.size());
-
-      fields.put("EOF", true);
-      Tuple tuple = new Tuple(fields);
+      Tuple tuple = Tuple.EOF();
+      tuple.put("rows", tuples.size());
       return tuple;
     }
 
@@ -395,7 +390,7 @@ public class Facet2DStream extends TupleStream implements Expressible {
   }
 
   private void getTuples(NamedList response, Bucket x, Bucket y, Metric metric) {
-    Tuple tuple = new Tuple(new HashMap());
+    Tuple tuple = new Tuple();
     NamedList facets = (NamedList) response.get("facets");
     fillTuples(0, tuples, tuple, facets, x, y, metric);
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
index b2b2809..f5cdaec 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
@@ -20,10 +20,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.stream.Collectors;
@@ -592,15 +590,11 @@ public class FacetStream extends TupleStream implements Expressible  {
       ++index;
       return tuple;
     } else {
-      Map fields = new HashMap();
+      Tuple tuple = Tuple.EOF();
 
       if(bucketSizeLimit == Integer.MAX_VALUE) {
-        fields.put("totalRows", tuples.size());
+        tuple.put("totalRows", tuples.size());
       }
-
-      fields.put("EOF", true);
-
-      Tuple tuple = new Tuple(fields);
       return tuple;
     }
   }
@@ -728,7 +722,7 @@ public class FacetStream extends TupleStream implements Expressible  {
                                 Bucket[] buckets,
                                 Metric[] metrics) {
 
-    Tuple tuple = new Tuple(new HashMap());
+    Tuple tuple = new Tuple();
     NamedList facets = (NamedList)response.get("facets");
     fillTuples(0,
                tuples,
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FeaturesSelectionStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FeaturesSelectionStream.java
index a9963d0..041e7c3 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FeaturesSelectionStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FeaturesSelectionStream.java
@@ -362,21 +362,19 @@ public class FeaturesSelectionStream extends TupleStream implements Expressible{
         for (Map.Entry<String, Double> termScore : termScores.entrySet()) {
           if (tuples.size() == numTerms) break;
           index++;
-          Map map = new HashMap();
-          map.put(ID, featureSet + "_" + index);
-          map.put("index_i", index);
-          map.put("term_s", termScore.getKey());
-          map.put("score_f", termScore.getValue());
-          map.put("featureSet_s", featureSet);
+          Tuple tuple = new Tuple();
+          tuple.put(ID, featureSet + "_" + index);
+          tuple.put("index_i", index);
+          tuple.put("term_s", termScore.getKey());
+          tuple.put("score_f", termScore.getValue());
+          tuple.put("featureSet_s", featureSet);
           long docFreq = docFreqs.get(termScore.getKey());
           double d = Math.log(((double)numDocs / (double)(docFreq + 1)));
-          map.put("idf_d", d);
-          tuples.add(new Tuple(map));
+          tuple.put("idf_d", d);
+          tuples.add(tuple);
         }
 
-        Map map = new HashMap();
-        map.put("EOF", true);
-        tuples.add(new Tuple(map));
+        tuples.add(Tuple.EOF());
 
         tupleIterator = tuples.iterator();
       }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/GetStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/GetStream.java
index 1655bfb..54a44b0 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/GetStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/GetStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -89,14 +88,11 @@ public class GetStream extends TupleStream implements Expressible {
   }
 
   public Tuple read() throws IOException {
-    Map map = new HashMap();
-    if(tupleIterator.hasNext()) {
+    if (tupleIterator.hasNext()) {
       Tuple t = tupleIterator.next();
-      map.putAll(t.fields);
-      return new Tuple(map);
+      return new Tuple(t.fields);
     } else {
-      map.put("EOF", true);
-      return new Tuple(map);
+      return Tuple.EOF();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/HashRollupStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/HashRollupStream.java
index 8bf82c6..0754692 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/HashRollupStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/HashRollupStream.java
@@ -199,18 +199,16 @@ public class HashRollupStream extends TupleStream implements Expressible {
         if (tuple.EOF) {
           List tuples = new ArrayList();
           for(Map.Entry<HashKey, Metric[]> entry : metricMap.entrySet()) {
-            Map<String, Object> map = new HashMap<String, Object>();
+            Tuple t = new Tuple();
             Metric[] finishedMetrics = entry.getValue();
             for (Metric metric : finishedMetrics) {
-              map.put(metric.getIdentifier(), metric.getValue());
+              t.put(metric.getIdentifier(), metric.getValue());
             }
 
             HashKey hashKey = entry.getKey();
             for (int i = 0; i < buckets.length; i++) {
-              map.put(buckets[i].toString(), hashKey.getParts()[i]);
+              t.put(buckets[i].toString(), hashKey.getParts()[i]);
             }
-
-            Tuple t = new Tuple(map);
             tuples.add(t);
           }
           tuples.add(tuple);
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/JDBCStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/JDBCStream.java
index ea40715..778f60c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/JDBCStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/JDBCStream.java
@@ -31,11 +31,9 @@ import java.sql.Timestamp;
 import java.sql.Types;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Properties;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -50,6 +48,7 @@ import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionNamedParamete
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionParameter;
 import org.apache.solr.client.solrj.io.stream.expr.StreamExpressionValue;
 import org.apache.solr.client.solrj.io.stream.expr.StreamFactory;
+import org.apache.solr.common.params.StreamParams;
 
 import static org.apache.solr.common.params.CommonParams.SORT;
 
@@ -515,22 +514,20 @@ public class JDBCStream extends TupleStream implements Expressible {
   
   public Tuple read() throws IOException {
     
-    try{
-      Map<Object,Object> fields = new HashMap<>();
-      if(resultSet.next()){
+    try {
+      Tuple tuple = new Tuple();
+      if (resultSet.next()) {
         // we have a record
-        for(ResultSetValueSelector selector : valueSelectors){
-          fields.put(selector.getColumnName(), selector.selectValue(resultSet));
+        for (ResultSetValueSelector selector : valueSelectors) {
+          tuple.put(selector.getColumnName(), selector.selectValue(resultSet));
         }
-      }
-      else{
+      } else {
         // we do not have a record
-        fields.put("EOF", true);
+        tuple.put(StreamParams.EOF, true);
       }
       
-      return new Tuple(fields);
-    }
-    catch(SQLException e){
+      return tuple;
+    } catch (SQLException e) {
       throw new IOException(String.format(Locale.ROOT, "Failed to read next record with error '%s'", e.getMessage()), e);
     }
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/KnnStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/KnnStream.java
index c03db38..39c9cd6 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/KnnStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/KnnStream.java
@@ -225,17 +225,14 @@ public class KnnStream extends TupleStream implements Expressible  {
 
   public Tuple read() throws IOException {
     if(documentIterator.hasNext()) {
-      Map map = new HashMap();
+      Tuple tuple = new Tuple();
       SolrDocument doc = documentIterator.next();
       for(Entry<String, Object> entry : doc.entrySet()) {
-        map.put(entry.getKey(), entry.getValue());
+        tuple.put(entry.getKey(), entry.getValue());
       }
-      return new Tuple(map);
-    } else {
-      Map fields = new HashMap();
-      fields.put("EOF", true);
-      Tuple tuple = new Tuple(fields);
       return tuple;
+    } else {
+      return Tuple.EOF();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ListStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ListStream.java
index 33f8fd5..3858df5 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ListStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ListStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -114,9 +113,7 @@ public class ListStream extends TupleStream implements Expressible {
           streams[streamIndex] = null;
           currentStream.open();
         } else {
-          HashMap map = new HashMap();
-          map.put("EOF", true);
-          return new Tuple(map);
+          return Tuple.EOF();
         }
       }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ModelStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ModelStream.java
index ffaf313..f13e736 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ModelStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ModelStream.java
@@ -193,9 +193,7 @@ public class ModelStream extends TupleStream implements Expressible {
       tuple = model;
       model = null;
     } else {
-      Map map = new HashMap();
-      map.put("EOF", true);
-      tuple = new Tuple(map);
+      tuple = Tuple.EOF();
     }
 
     return tuple;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NoOpStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NoOpStream.java
index 8d55c31..85a0f55 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NoOpStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NoOpStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 
 import org.apache.solr.client.solrj.io.Tuple;
@@ -88,10 +87,7 @@ public class NoOpStream extends TupleStream implements Expressible {
   }
 
   public Tuple read() throws IOException {
-      HashMap m = new HashMap();
-      m.put("EOF", true);
-      Tuple tuple = new Tuple(m);
-      return tuple;
+    return Tuple.EOF();
   }
 
   /** Return the stream sort - ie, the order in which records are returned */
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NullStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NullStream.java
index 4f0181b..067acb5 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NullStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/NullStream.java
@@ -18,7 +18,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Date;
 
@@ -133,7 +132,7 @@ public class NullStream extends TupleStream implements Expressible {
       if(tuple.EOF) {
         eof = tuple;
         long end = new Date().getTime();
-        Tuple t = new Tuple(new HashMap());
+        Tuple t = new Tuple();
         t.put("nullCount", count);
         t.put("timer", end-start);
         return t;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelListStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelListStream.java
index aeadd90..dbf2901 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelListStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelListStream.java
@@ -19,7 +19,6 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -107,14 +106,12 @@ public class ParallelListStream extends TupleStream implements Expressible {
   }
 
   public Tuple read() throws IOException {
-    while(true) {
+    while (true) {
       if (currentStream == null) {
         if (streamIndex < streams.length) {
           currentStream = streams[streamIndex];
         } else {
-          HashMap map = new HashMap();
-          map.put("EOF", true);
-          return new Tuple(map);
+          return Tuple.EOF();
         }
       }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelStream.java
index d81aa54..141411e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ParallelStream.java
@@ -18,10 +18,8 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.FieldComparator;
@@ -217,10 +215,6 @@ public class ParallelStream extends CloudSolrStream implements Expressible {
     Tuple tuple = _read();
 
     if(tuple.EOF) {
-      Map m = new HashMap();
-      m.put("EOF", true);
-      Tuple t = new Tuple(m);
-
       /*
       Map<String, Map> metrics = new HashMap();
       Iterator<Entry<String,Tuple>> it = this.eofTuples.entrySet().iterator();
@@ -235,7 +229,7 @@ public class ParallelStream extends CloudSolrStream implements Expressible {
         t.setMetrics(metrics);
       }
       */
-      return t;
+      return Tuple.EOF();
     }
 
     return tuple;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/PlotStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/PlotStream.java
index a83349a..842cad3 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/PlotStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/PlotStream.java
@@ -150,10 +150,8 @@ public class PlotStream extends TupleStream implements Expressible {
 
   public Tuple read() throws IOException {
 
-    if(finished) {
-      Map<String,Object> m = new HashMap<>();
-      m.put("EOF", true);
-      return new Tuple(m);
+    if (finished) {
+      return Tuple.EOF();
     } else {
       finished = true;
       Map<String, Object> values = new HashMap<>();
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
index aca0e3d..20a055c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
@@ -234,25 +234,22 @@ public class RandomStream extends TupleStream implements Expressible  {
 
   public Tuple read() throws IOException {
     if(documentIterator.hasNext()) {
-      Map map = new HashMap();
+      Tuple tuple = new Tuple();
       SolrDocument doc = documentIterator.next();
 
       // Put the generated x-axis first. If there really is an x field it will overwrite it.
       if(outputX) {
-        map.put("x", x++);
+        tuple.put("x", x++);
       }
 
       for(Entry<String, Object> entry : doc.entrySet()) {
-        map.put(entry.getKey(), entry.getValue());
+        tuple.put(entry.getKey(), entry.getValue());
       }
 
 
-      return new Tuple(map);
-    } else {
-      Map fields = new HashMap();
-      fields.put("EOF", true);
-      Tuple tuple = new Tuple(fields);
       return tuple;
+    } else {
+      return Tuple.EOF();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RollupStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RollupStream.java
index c1b6894..0de3634 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RollupStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RollupStream.java
@@ -237,15 +237,14 @@ public class RollupStream extends TupleStream implements Expressible {
       } else {
         Tuple t = null;
         if(currentMetrics != null) {
-          Map<String,Object> map = new HashMap<String,Object>();
+          t = new Tuple();
           for(Metric metric : currentMetrics) {
-            map.put(metric.getIdentifier(), metric.getValue());
+            t.put(metric.getIdentifier(), metric.getValue());
           }
 
           for(int i=0; i<buckets.length; i++) {
-            map.put(buckets[i].toString(), currentKey.getParts()[i]);
+            t.put(buckets[i].toString(), currentKey.getParts()[i]);
           }
-          t = new Tuple(map);
         }
 
         currentKey = hashKey;
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ScoreNodesStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ScoreNodesStream.java
index a7bb15d..a9900db 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ScoreNodesStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ScoreNodesStream.java
@@ -265,9 +265,7 @@ public class ScoreNodesStream extends TupleStream implements Expressible
     if(tuples.hasNext()) {
       return tuples.next();
     } else {
-      Map map = new HashMap();
-      map.put("EOF", true);
-      return new Tuple(map);
+      return Tuple.EOF();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SearchStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SearchStream.java
index 24368a0..2d96d60 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SearchStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SearchStream.java
@@ -19,12 +19,10 @@ package org.apache.solr.client.solrj.io.stream;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 
@@ -208,17 +206,14 @@ public class SearchStream extends TupleStream implements Expressible  {
 
   public Tuple read() throws IOException {
     if(documentIterator.hasNext()) {
-      Map map = new HashMap();
+      Tuple tuple = new Tuple();
       SolrDocument doc = documentIterator.next();
       for(Entry<String, Object> entry : doc.entrySet()) {
-        map.put(entry.getKey(), entry.getValue());
+        tuple.put(entry.getKey(), entry.getValue());
       }
-      return new Tuple(map);
-    } else {
-      Map fields = new HashMap();
-      fields.put("EOF", true);
-      Tuple tuple = new Tuple(fields);
       return tuple;
+    } else {
+      return Tuple.EOF();
     }
   }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SelectStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SelectStream.java
index c538560..4ec4d36 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SelectStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SelectStream.java
@@ -257,8 +257,8 @@ public class SelectStream extends TupleStream implements Expressible {
     }
 
     // create a copy with the limited set of fields
-    Tuple workingToReturn = new Tuple(new HashMap<>());
-    Tuple workingForEvaluators = new Tuple(new HashMap<>());
+    Tuple workingToReturn = new Tuple();
+    Tuple workingForEvaluators = new Tuple();
 
     //Clear the TupleContext before running the evaluators.
     //The TupleContext allows evaluators to cache values within the scope of a single tuple.
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SignificantTermsStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SignificantTermsStream.java
index c3a120f..ac100b3 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SignificantTermsStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SignificantTermsStream.java
@@ -335,9 +335,7 @@ public class SignificantTermsStream extends TupleStream implements Expressible{
           tuples.add(new Tuple(map));
         }
 
-        Map map = new HashMap();
-        map.put("EOF", true);
-        tuples.add(new Tuple(map));
+        tuples.add(Tuple.EOF());
         tupleIterator = tuples.iterator();
       }
 
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
index d1b666d..b03995f 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
@@ -203,9 +203,7 @@ public class SolrStream extends TupleStream {
 
       if (fields == null) {
         //Return the EOF tuple.
-        Map m = new HashMap();
-        m.put(StreamParams.EOF, true);
-        return new Tuple(m);
+        return Tuple.EOF();
       } else {
 
         String msg = (String) fields.get(StreamParams.EXCEPTION);
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
index c497290..3b12cf8 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
@@ -257,9 +257,7 @@ public class StatsStream extends TupleStream implements Expressible  {
       done = true;
       return tuple;
     } else {
-      Map<String, Object> fields = new HashMap<>();
-      fields.put("EOF", true);
-      return new Tuple(fields);
+      return Tuple.EOF();
     }
   }
 
@@ -315,14 +313,13 @@ public class StatsStream extends TupleStream implements Expressible  {
   }
 
   private Tuple getTuple(NamedList response) {
-
-    Map<String, Object> map = new HashMap<>();
+    Tuple tuple = new Tuple();
     SolrDocumentList solrDocumentList = (SolrDocumentList) response.get("response");
 
     long count = solrDocumentList.getNumFound();
 
     if(doCount) {
-      map.put("count(*)", count);
+      tuple.put("count(*)", count);
     }
 
     if(count != 0) {
@@ -333,30 +330,29 @@ public class StatsStream extends TupleStream implements Expressible  {
         String field = statsFields.getName(i);
         NamedList theStats = (NamedList)statsFields.getVal(i);
         for(int s=0; s<theStats.size(); s++) {
-          addStat(map, field, theStats.getName(s), theStats.getVal(s));
+          addStat(tuple, field, theStats.getName(s), theStats.getVal(s));
         }
       }
     }
-
-    return new Tuple(map);
+    return tuple;
   }
 
   public int getCost() {
     return 0;
   }
 
-  private void addStat(Map<String, Object> map, String field, String stat, Object val) {
+  private void addStat(Tuple tuple, String field, String stat, Object val) {
     if(stat.equals("mean")) {
       String name = "avg("+field+")";
       Metric m = metricMap.get(name);
       if(m.outputLong) {
         Number num = (Number) val;
-        map.put(name, Math.round(num.doubleValue()));
+        tuple.put(name, Math.round(num.doubleValue()));
       } else {
-        map.put(name, val);
+        tuple.put(name, val);
       }
     } else {
-      map.put(stat+"("+field+")", val);
+      tuple.put(stat+"("+field+")", val);
     }
   }
 }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TextLogitStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TextLogitStream.java
index 819d3ae..3e6666d 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TextLogitStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TextLogitStream.java
@@ -442,9 +442,7 @@ public class TextLogitStream extends TupleStream implements Expressible {
     try {
 
       if(++iteration > maxIterations) {
-        Map map = new HashMap();
-        map.put("EOF", true);
-        return new Tuple(map);
+        return Tuple.EOF();
       } else {
 
         if (this.idfs == null) {
@@ -560,14 +558,13 @@ public class TextLogitStream extends TupleStream implements Expressible {
 
     @Override
     public Tuple read() throws IOException {
-      HashMap map = new HashMap();
-      if(it.hasNext()) {
-        map.put("term_s",it.next());
-        map.put("score_f",1.0);
-        return new Tuple(map);
+      if (it.hasNext()) {
+        Tuple tuple = new Tuple();
+        tuple.put("term_s", it.next());
+        tuple.put("score_f", 1.0);
+        return tuple;
       } else {
-        map.put("EOF", true);
-        return new Tuple(map);
+        return Tuple.EOF();
       }
     }
 
@@ -650,13 +647,13 @@ public class TextLogitStream extends TupleStream implements Expressible {
       List<Double> shardWeights = (List<Double>)logit.get("weights");
       double shardError = (double)logit.get("error");
 
-      Map map = new HashMap();
+      Tuple tuple = new Tuple();
 
-      map.put("error", shardError);
-      map.put("weights", shardWeights);
-      map.put("evaluation", logit.get("evaluation"));
+      tuple.put("error", shardError);
+      tuple.put("weights", shardWeights);
+      tuple.put("evaluation", logit.get("evaluation"));
 
-      return new Tuple(map);
+      return tuple;
     }
   }
 }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
index bccc438..cf6ffbd 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
@@ -328,10 +328,7 @@ public class TimeSeriesStream extends TupleStream implements Expressible  {
       ++index;
       return tuple;
     } else {
-      Map fields = new HashMap();
-      fields.put("EOF", true);
-      Tuple tuple = new Tuple(fields);
-      return tuple;
+      return Tuple.EOF();
     }
   }
 
@@ -377,7 +374,7 @@ public class TimeSeriesStream extends TupleStream implements Expressible  {
                          String field,
                          Metric[] metrics) {
 
-    Tuple tuple = new Tuple(new HashMap());
+    Tuple tuple = new Tuple();
     NamedList facets = (NamedList)response.get("facets");
     fillTuples(tuples, tuple, facets, field, metrics);
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TupStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TupStream.java
index a7bca77..fc8f213 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TupStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TupStream.java
@@ -152,9 +152,7 @@ public class TupStream extends TupleStream implements Expressible {
 
     if(unnestedTuples == null) {
       if (finished) {
-        Map<String, Object> m = new HashMap<>();
-        m.put("EOF", true);
-        return new Tuple(m);
+        return Tuple.EOF();
       } else {
         finished = true;
         if(unnestedTuple != null) {
@@ -167,9 +165,7 @@ public class TupStream extends TupleStream implements Expressible {
       if(unnestedTuples.hasNext()) {
         return unnestedTuples.next();
       } else {
-        Map<String, Object> m = new HashMap<>();
-        m.put("EOF", true);
-        return new Tuple(m);
+        return Tuple.EOF();
       }
     }
   }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
index 5313f14..07f12be 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
@@ -347,16 +347,16 @@ public class UpdateStream extends TupleStream implements Expressible {
   
   private Tuple createBatchSummaryTuple(int batchSize) {
     assert batchSize > 0;
-    Map m = new HashMap();
+    Tuple tuple = new Tuple();
     this.totalDocsIndex += batchSize;
     ++batchNumber;
-    m.put(BATCH_INDEXED_FIELD_NAME, batchSize);
-    m.put("totalIndexed", this.totalDocsIndex);
-    m.put("batchNumber", batchNumber);
-    if(coreName != null) {
-      m.put("worker", coreName);
+    tuple.put(BATCH_INDEXED_FIELD_NAME, batchSize);
+    tuple.put("totalIndexed", this.totalDocsIndex);
+    tuple.put("batchNumber", batchNumber);
+    if (coreName != null) {
+      tuple.put("worker", coreName);
     }
-    return new Tuple(m);
+    return tuple;
   }
 
 }
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ZplotStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ZplotStream.java
index a85c33e..6beedc4 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ZplotStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/ZplotStream.java
@@ -198,7 +198,7 @@ public class ZplotStream extends TupleStream implements Expressible {
     if(!table && !distribution && !clusters && !heat) {
       //Handle the vectors
       for (int i = 0; i < numTuples; i++) {
-        Tuple tuple = new Tuple(new HashMap());
+        Tuple tuple = new Tuple();
         for (Map.Entry<String, Object> entry : evaluated.entrySet()) {
           List l = (List) entry.getValue();
           tuple.put(entry.getKey(), l.get(i));
@@ -224,7 +224,7 @@ public class ZplotStream extends TupleStream implements Expressible {
           clusterNum++;
           List<KmeansEvaluator.ClusterPoint> points = c.getPoints();
           for (KmeansEvaluator.ClusterPoint p : points) {
-            Tuple tuple = new Tuple(new HashMap());
+            Tuple tuple = new Tuple();
             tuple.put("x", p.getPoint()[0]);
             tuple.put("y", p.getPoint()[1]);
             tuple.put("cluster", "cluster" + clusterNum);
@@ -239,7 +239,7 @@ public class ZplotStream extends TupleStream implements Expressible {
           clusterNum++;
           List<DbscanEvaluator.ClusterPoint> points = c.getPoints();
           for (DbscanEvaluator.ClusterPoint p : points) {
-            Tuple tuple = new Tuple(new HashMap());
+            Tuple tuple = new Tuple();
             tuple.put("x", p.getPoint()[0]);
             tuple.put("y", p.getPoint()[1]);
             tuple.put("cluster", "cluster" + clusterNum);
@@ -269,7 +269,7 @@ public class ZplotStream extends TupleStream implements Expressible {
         }
 
         for (int i = 0; i < x.length; i++) {
-          Tuple tuple = new Tuple(new HashMap());
+          Tuple tuple = new Tuple();
           if(!Double.isNaN(x[i])) {
             tuple.put("x", Precision.round(x[i], 2));
             if(y[i] == Double.NEGATIVE_INFINITY || y[i] == Double.POSITIVE_INFINITY) {
@@ -302,7 +302,7 @@ public class ZplotStream extends TupleStream implements Expressible {
         }
 
         for (int i = 0; i < x.length; i++) {
-          Tuple tuple = new Tuple(new HashMap());
+          Tuple tuple = new Tuple();
           tuple.put("x", x[i]);
           tuple.put("y", y[i]);
           outTuples.add(tuple);
@@ -314,14 +314,14 @@ public class ZplotStream extends TupleStream implements Expressible {
           Tuple tuple = tlist.get(0);
           if(tuple.fields.containsKey("N")) {
             for(Tuple t : tlist) {
-              Tuple outtuple = new Tuple(new HashMap());
+              Tuple outtuple = new Tuple();
               outtuple.put("x", Precision.round(((double)t.get("mean")), 2));
               outtuple.put("y", t.get("prob"));
               outTuples.add(outtuple);
             }
           } else if(tuple.fields.containsKey("count")) {
             for(Tuple t : tlist) {
-              Tuple outtuple = new Tuple(new HashMap());
+              Tuple outtuple = new Tuple();
               outtuple.put("x", t.get("value"));
               outtuple.put("y", t.get("pct"));
               outTuples.add(outtuple);
@@ -344,7 +344,7 @@ public class ZplotStream extends TupleStream implements Expressible {
           } else {
             rowLabel = Integer.toString(i);
           }
-          Tuple tuple = new Tuple(new HashMap());
+          Tuple tuple = new Tuple();
           tuple.put("rowLabel", rowLabel);
           double[] row = data[i];
           for (int j = 0; j < row.length; j++) {
@@ -378,7 +378,7 @@ public class ZplotStream extends TupleStream implements Expressible {
 
           double[] row = data[i];
           for (int j = 0; j < row.length; j++) {
-            Tuple tuple = new Tuple(new HashMap());
+            Tuple tuple = new Tuple();
             tuple.put("y", rowLabel);
             String colLabel = null;
             if (colLabels != null) {
diff --git a/solr/solrj/src/java/org/apache/solr/common/params/StreamParams.java b/solr/solrj/src/java/org/apache/solr/common/params/StreamParams.java
index 88654f9..a82d81e 100644
--- a/solr/solrj/src/java/org/apache/solr/common/params/StreamParams.java
+++ b/solr/solrj/src/java/org/apache/solr/common/params/StreamParams.java
@@ -24,14 +24,18 @@ public interface StreamParams {
   // parameters
   String EXPR = "expr";
 
-  // properties
+  // stream properties
   String TUPLE = "tuple";
   String DOCS = "docs";
   String RETURN_VALUE = "return-value";
   String RESULT_SET = "result-set";
 
+  // tuple properties
   String RESPONSE_TIME = "RESPONSE_TIME";
   String EOF = "EOF";
   String EXCEPTION = "EXCEPTION";
   String METRICS = "_METRICS_";
+
+  // other common tuple properties
+  String P_VALUE = "p-value";
 }