title: Implementing Java Pivot table using Streams
body: <p>I have been struggling with this issue for a few days now.  I am trying to create Pivot functionality using Java Streams.  I only have to implement
  SUM, COUNT, MAX, MIN, and AVERAGE.  For input I am given a Pivot Column Index, an array of pivot row indexes, and the value to calculate.</p>
  
  <p>The catch is the data is in a List &lt; List &lt; Object>>, Where Object with either be String, Integer, or Double.  but I won't know until runtime.  And I have to return my results as List &lt; List &lt; Object>>.</p>
  
  <p>I am having trouble with MAX/MIN (I am assuming that AVERAGE will be similar to MAX and MIN)</p>
  
  <p>In order to pivot on multiple table values, I created a class to using my my second groupingBy</p>
  
  <p>This will not compile, I am not sure what to Compare against, where to convert the object to int or if I even need to.  I would like to do this all with one stream, but I am not sure it is possible.  What am I doing wrong, or could I do it differently.  Thanks in advance.</p>
  
  <pre><code>package pivot.test;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.List;
  import java.util.Map;
  import java.util.Optional;
  import java.util.stream.Collectors;
  
  public class PivotTest {
  
      List&lt;List&lt;Object&gt;&gt; rows = new ArrayList&lt;List&lt;Object&gt;&gt;();
  
      public PivotTest() throws Exception {
  
          rows.add(Arrays.asList(new Object[]{ "East", "Boy", "Tee", 10, 12.00}));
          rows.add(Arrays.asList(new Object[]{ "East", "Boy", "Golf", 15, 20.00}));
          rows.add(Arrays.asList(new Object[]{ "East", "Girl", "Tee", 8, 14.00}));
          rows.add(Arrays.asList(new Object[]{ "East", "Girl", "Golf", 20, 24.00}));
          rows.add(Arrays.asList(new Object[]{ "West", "Boy", "Tee", 5, 12.00}));
          rows.add(Arrays.asList(new Object[]{ "West", "Boy", "Golf", 12, 20.00}));
          rows.add(Arrays.asList(new Object[]{ "West", "Girl", "Tee", 15, 14.00}));
          rows.add(Arrays.asList(new Object[]{ "West", "Girl", "Golf", 10, 24.00}));
  
      }
  
      // Dynamic Max based upon Column, Value to sum, and an array of pivot rows
      public void MaxTable(int colIdx, int valueIdx, int... rowIdx) {
  
           Map&lt;Object, Map&lt;Object, Integer&gt;&gt; myList = newRows.stream().collect(
           Collectors.groupingBy(r -&gt; ((List&lt;Object&gt;) r).get(colIdx),
           Collectors.groupingBy( r -&gt; new PivotColumns(r, rowIdx),
           Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparingInt(???)),
                  r -&gt; ((List&lt;Object&gt;) r).get(valueIdx)))));
  
           System.out.println("Dynamic MAX PIVOT"); System.out.println(myList);
  
      }
  
      public static void main(String[] args) {
  
          try {
              PivotTest p = new PivotTest();
              System.out.println("\n\nStreams PIVOT with index values inside a List\n");
              p.MaxTable(0, 3, new int[] { 2 });
          } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      }
  
  }
  
  class PivotColumns {
  
      ArrayList&lt;Object&gt; columns;
  
      public PivotColumns(
          List&lt;Object&gt; objs, int... pRows) {
          columns = new ArrayList&lt;Object&gt;();
  
          for (int i = 0; i &lt; pRows.length; i++) {
              columns.add(objs.get(pRows[i]));
          }
  
      }
  
      public void addObject(Object obj) {
          columns.add(obj);
      }
  
      @Override
      public int hashCode() {
          final int prime = 31;
          int result = 1;
          result = prime * result + ((columns == null) ? 0 : columns.hashCode());
          return result;
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj)
              return true;
          if (obj == null)
              return false;
          if (getClass() != obj.getClass())
              return false;
          PivotColumns other = (PivotColumns) obj;
          if (columns == null) {
              if (other.columns != null)
                  return false;
          } else if (!columns.equals(other.columns))
              return false;
          return true;
      }
  
      public String toString() {
          String s = "";
          for (Object obj : columns) {
              s += obj + ",";
          }
  
          return s.substring(0, s.lastIndexOf(','));
      }
  
  }
  </code></pre>