You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/10/07 23:57:54 UTC

incubator-tinkerpop git commit: Removed GroupCountStep where groupCount() just calls GroupStep under the hood. Super simple to do and now we have 2 less steps to maintain.

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP3-872 [created] db1cd97e3


Removed GroupCountStep where groupCount() just calls GroupStep under the hood. Super simple to do and now we have 2 less steps to maintain.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/db1cd97e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/db1cd97e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/db1cd97e

Branch: refs/heads/TINKERPOP3-872
Commit: db1cd97e3ec98938961e394489dd902acbb3009f
Parents: e54f0aa
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Oct 7 15:57:43 2015 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Oct 7 15:57:43 2015 -0600

----------------------------------------------------------------------
 .../traversal/dsl/graph/GraphTraversal.java     |  10 +-
 .../traversal/step/map/GroupCountStep.java      | 182 -------------------
 .../process/traversal/step/map/GroupStep.java   |  61 ++++---
 .../sideEffect/GroupCountSideEffectStep.java    | 174 ------------------
 .../step/sideEffect/GroupSideEffectStep.java    |  55 ++++--
 5 files changed, 76 insertions(+), 406 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/db1cd97e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index f91fed9..7d08407 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -72,7 +72,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.DedupLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStepV3d0;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
@@ -111,7 +110,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStepV3d0;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
@@ -627,7 +625,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default <K, V> GraphTraversal<S, Map<K, V>> group() {
-        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin()));
+        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin(), false));
     }
 
     /**
@@ -639,7 +637,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default <K> GraphTraversal<S, Map<K, Long>> groupCount() {
-        return this.asAdmin().addStep(new GroupCountStep<>(this.asAdmin()));
+        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin(), true));
     }
 
     public default GraphTraversal<S, Tree> tree() {
@@ -966,7 +964,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default GraphTraversal<S, E> group(final String sideEffectKey) {
-        return this.asAdmin().addStep(new GroupSideEffectStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new GroupSideEffectStep<>(this.asAdmin(), sideEffectKey, false));
     }
 
     /**
@@ -977,7 +975,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default GraphTraversal<S, E> groupCount(final String sideEffectKey) {
-        return this.asAdmin().addStep(new GroupCountSideEffectStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new GroupSideEffectStep<>(this.asAdmin(), sideEffectKey, true));
     }
 
     public default GraphTraversal<S, E> tree(final String sideEffectKey) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/db1cd97e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
deleted file mode 100644
index 7f3904e..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step.map;
-
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiFunction;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupCountStep<S, E> extends ReducingBarrierStep<S, Map<E, Long>> implements MapReducer, TraversalParent {
-
-    private Traversal.Admin<S, E> groupTraversal = null;
-
-    public GroupCountStep(final Traversal.Admin traversal) {
-        super(traversal);
-        this.setSeedSupplier(HashMapSupplier.instance());
-        this.setBiFunction(new GroupCountBiFunction(this));
-    }
-
-
-    @Override
-    public void addLocalChild(final Traversal.Admin<?, ?> groupTraversal) {
-        this.groupTraversal = this.integrateChild(groupTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, E>> getLocalChildren() {
-        return null == this.groupTraversal ? Collections.emptyList() : Collections.singletonList(this.groupTraversal);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.BULK);
-    }
-
-    @Override
-    public MapReduce<E, Long, E, Long, Map<E, Long>> getMapReduce() {
-        return GroupCountMapReduce.instance();
-    }
-
-    @Override
-    public GroupCountStep<S, E> clone() {
-        final GroupCountStep<S, E> clone = (GroupCountStep<S, E>) super.clone();
-        if (null != this.groupTraversal)
-            clone.groupTraversal = clone.integrateChild(this.groupTraversal.clone());
-        clone.setBiFunction(new GroupCountBiFunction<>(clone));
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode();
-        for (final Traversal.Admin<S, E> traversal : this.getLocalChildren()) {
-            result ^= traversal.hashCode();
-        }
-        return result;
-    }
-
-    @Override
-    public Traverser<Map<E, Long>> processNextStart() {
-        if (this.byPass) {
-            final Traverser.Admin<S> traverser = this.starts.next();
-            return traverser.asAdmin().split(TraversalUtil.applyNullable(traverser, (Traversal.Admin<S, Map<E, Long>>) this.groupTraversal), this);
-        } else {
-            return super.processNextStart();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.groupTraversal);
-    }
-
-    ///////////
-
-    private static class GroupCountBiFunction<S, E> implements BiFunction<Map<E, Long>, Traverser<S>, Map<E, Long>>, Serializable {
-
-        private final GroupCountStep<S, E> groupCountStep;
-
-        private GroupCountBiFunction(final GroupCountStep<S, E> groupCountStep) {
-            this.groupCountStep = groupCountStep;
-
-        }
-
-        @Override
-        public Map<E, Long> apply(final Map<E, Long> mutatingSeed, final Traverser<S> traverser) {
-            MapHelper.incr(mutatingSeed, TraversalUtil.applyNullable(traverser.asAdmin(), this.groupCountStep.groupTraversal), traverser.bulk());
-            return mutatingSeed;
-        }
-    }
-
-    ///////////
-
-    public static final class GroupCountMapReduce<E> extends StaticMapReduce<E, Long, E, Long, Map<E, Long>> {
-
-        private static final GroupCountMapReduce INSTANCE = new GroupCountMapReduce();
-
-        private GroupCountMapReduce() {
-
-        }
-
-        @Override
-        public boolean doStage(final Stage stage) {
-            return true;
-        }
-
-        @Override
-        public void map(final Vertex vertex, final MapEmitter<E, Long> emitter) {
-            vertex.<TraverserSet<E>>property(TraversalVertexProgram.HALTED_TRAVERSERS).ifPresent(traverserSet -> traverserSet.forEach(traverser -> emitter.emit(traverser.get(), traverser.bulk())));
-        }
-
-        @Override
-        public void reduce(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            long counter = 0;
-            while (values.hasNext()) {
-                counter = counter + values.next();
-            }
-            emitter.emit(key, counter);
-        }
-
-        @Override
-        public void combine(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            reduce(key, values, emitter);
-        }
-
-        @Override
-        public Map<E, Long> generateFinalResult(final Iterator<KeyValue<E, Long>> keyValues) {
-            final Map<E, Long> map = new HashMap<>();
-            keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-            return map;
-        }
-
-        @Override
-        public String getMemoryKey() {
-            return REDUCING;
-        }
-
-        public static final <E> GroupCountMapReduce<E> instance() {
-            return INSTANCE;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/db1cd97e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
index d13f24d..dd0468f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
@@ -60,19 +60,29 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
     private char state = 'k';
 
     private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, ?> valueTraversal = this.integrateChild(__.identity().asAdmin());   // used in OLAP
-    private Traversal.Admin<?, V> reduceTraversal = this.integrateChild(__.fold().asAdmin());      // used in OLAP
-    private Traversal.Admin<S, V> valueReduceTraversal = this.integrateChild(__.fold().asAdmin()); // used in OLTP
+    private Traversal.Admin<S, ?> valueTraversal;       // used in OLAP
+    private Traversal.Admin<?, V> reduceTraversal;      // used in OLAP
+    private Traversal.Admin<S, V> valueReduceTraversal; // used in OLTP
+    private boolean groupCount = false;
 
-    public GroupStep(final Traversal.Admin traversal) {
+    public GroupStep(final Traversal.Admin traversal, final boolean groupCount) {
         super(traversal);
         this.setSeedSupplier((Supplier) new GroupStepHelper.GroupMapSupplier());
         this.setBiFunction(new GroupBiFunction(this));
+        if (this.groupCount = groupCount) {
+            this.valueReduceTraversal = this.integrateChild(__.count().asAdmin());
+            this.valueTraversal = this.integrateChild(__.identity().asAdmin());
+            this.reduceTraversal = this.integrateChild(__.count().asAdmin());
+        } else {
+            this.valueTraversal = this.integrateChild(__.identity().asAdmin());
+            this.reduceTraversal = this.integrateChild(__.fold().asAdmin());
+            this.valueReduceTraversal = this.integrateChild(__.fold().asAdmin());
+        }
     }
 
     @Override
-    public List<Traversal.Admin<?,?>> getLocalChildren() {
-        final List<Traversal.Admin<?,?>> children = new ArrayList<>(4);
+    public List<Traversal.Admin<?, ?>> getLocalChildren() {
+        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(4);
         if (null != this.keyTraversal)
             children.add((Traversal.Admin) this.keyTraversal);
         children.add(this.valueReduceTraversal);
@@ -87,6 +97,8 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
             this.keyTraversal = this.integrateChild(kvTraversal);
             this.state = 'v';
         } else if ('v' == this.state) {
+            if (this.groupCount)
+                throw new IllegalStateException("The key traversal for groupCount()-step have already been set: " + this);
             this.valueReduceTraversal = this.integrateChild(GroupStepHelper.convertValueTraversal(kvTraversal));
             final List<Traversal.Admin<?, ?>> splitTraversal = GroupStepHelper.splitOnBarrierStep(this.valueReduceTraversal);
             this.valueTraversal = this.integrateChild(splitTraversal.get(0));
@@ -103,6 +115,24 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
     }
 
     @Override
+    public Traverser<Map<K, V>> processNextStart() {
+        if (this.byPass) {
+            final Traverser.Admin<S> traverser = this.starts.next();
+            final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
+            this.valueTraversal.addStart(traverser);
+            final BulkSet<?> value = this.valueTraversal.toBulkSet();
+            return traverser.asAdmin().split(new Object[]{key, value}, (Step) this);
+        } else {
+            return super.processNextStart();
+        }
+    }
+
+    @Override
+    public MapReduce<K, Collection<?>, K, V, Map<K, V>> getMapReduce() {
+        return new GroupMapReduce<>(this);
+    }
+
+    @Override
     public GroupStep<S, K, V> clone() {
         final GroupStep<S, K, V> clone = (GroupStep<S, K, V>) super.clone();
         if (null != this.keyTraversal)
@@ -118,28 +148,11 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
     public int hashCode() {
         int result = this.valueReduceTraversal.hashCode();
         if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
+        result ^= Boolean.valueOf(this.groupCount).hashCode();
         return result;
     }
 
     @Override
-    public MapReduce<K, Collection<?>, K, V, Map<K, V>> getMapReduce() {
-        return new GroupMapReduce<>(this);
-    }
-
-    @Override
-    public Traverser<Map<K, V>> processNextStart() {
-        if (this.byPass) {
-            final Traverser.Admin<S> traverser = this.starts.next();
-            final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
-            this.valueTraversal.addStart(traverser);
-            final BulkSet<?> value = this.valueTraversal.toBulkSet();
-            return traverser.asAdmin().split(new Object[]{key, value}, (Step) this);
-        } else {
-            return super.processNextStart();
-        }
-    }
-
-    @Override
     public String toString() {
         return StringFactory.stepString(this, this.keyTraversal, this.valueReduceTraversal);
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/db1cd97e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
deleted file mode 100644
index f26206a..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.util.*;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupCountSideEffectStep<S, E> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, MapReducer<E, Long, E, Long, Map<E, Long>> {
-
-    private Traversal.Admin<S, E> groupTraversal = null;
-    private String sideEffectKey;
-
-    public GroupCountSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
-    }
-
-    @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        final Map<Object, Long> groupCountMap = traverser.sideEffects(this.sideEffectKey);
-        MapHelper.incr(groupCountMap, TraversalUtil.applyNullable(traverser.asAdmin(), this.groupTraversal), traverser.bulk());
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public MapReduce<E, Long, E, Long, Map<E, Long>> getMapReduce() {
-        return new GroupCountSideEffectMapReduce<>(this);
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.groupTraversal);
-    }
-
-    @Override
-    public void addLocalChild(final Traversal.Admin<?, ?> groupTraversal) {
-        this.groupTraversal = this.integrateChild(groupTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, E>> getLocalChildren() {
-        return null == this.groupTraversal ? Collections.emptyList() : Collections.singletonList(this.groupTraversal);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
-    }
-
-    @Override
-    public GroupCountSideEffectStep<S, E> clone() {
-        final GroupCountSideEffectStep<S, E> clone = (GroupCountSideEffectStep<S, E>) super.clone();
-        if (null != this.groupTraversal)
-            clone.groupTraversal = clone.integrateChild(this.groupTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.groupTraversal != null) result ^= this.groupTraversal.hashCode();
-        return result;
-    }
-
-    ///////
-
-    public static final class GroupCountSideEffectMapReduce<E> extends StaticMapReduce<E, Long, E, Long, Map<E, Long>> {
-
-        public static final String GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY = "gremlin.groupCountSideEffectStep.sideEffectKey";
-
-        private String sideEffectKey;
-        private Supplier<Map<E, Long>> mapSupplier;
-
-        private GroupCountSideEffectMapReduce() {
-
-        }
-
-        public GroupCountSideEffectMapReduce(final GroupCountSideEffectStep step) {
-            this.sideEffectKey = step.getSideEffectKey();
-            this.mapSupplier = step.getTraversal().asAdmin().getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public void storeState(final Configuration configuration) {
-            super.storeState(configuration);
-            configuration.setProperty(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
-        }
-
-        @Override
-        public void loadState(final Graph graph, final Configuration configuration) {
-            this.sideEffectKey = configuration.getString(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY);
-            this.mapSupplier = TraversalVertexProgram.getTraversal(graph, configuration).getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public boolean doStage(final Stage stage) {
-            return true;
-        }
-
-        @Override
-        public void map(final Vertex vertex, final MapEmitter<E, Long> emitter) {
-            VertexTraversalSideEffects.of(vertex).<Map<E, Number>>get(this.sideEffectKey).ifPresent(map -> map.forEach((k, v) -> emitter.emit(k, v.longValue())));
-        }
-
-        @Override
-        public void reduce(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            long counter = 0;
-            while (values.hasNext()) {
-                counter = counter + values.next();
-            }
-            emitter.emit(key, counter);
-        }
-
-        @Override
-        public void combine(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            reduce(key, values, emitter);
-        }
-
-        @Override
-        public Map<E, Long> generateFinalResult(final Iterator<KeyValue<E, Long>> keyValues) {
-            final Map<E, Long> map = this.mapSupplier.get();
-            keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-            return map;
-        }
-
-        @Override
-        public String getMemoryKey() {
-            return this.sideEffectKey;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/db1cd97e/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
index ef3b88a..82c27f4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
@@ -59,18 +59,39 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
 
     private char state = 'k';
     private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, ?> valueTraversal = this.integrateChild(__.identity().asAdmin());   // used in OLAP
-    private Traversal.Admin<?, V> reduceTraversal = this.integrateChild(__.fold().asAdmin());      // used in OLAP
-    private Traversal.Admin<S, V> valueReduceTraversal = this.integrateChild(__.fold().asAdmin()); // used in OLTP
+    private Traversal.Admin<S, ?> valueTraversal;        // used in OLAP
+    private Traversal.Admin<?, V> reduceTraversal;       // used in OLAP
+    private Traversal.Admin<S, V> valueReduceTraversal;  // used in OLTP
     ///
     private String sideEffectKey;
+    private boolean groupCount = false;
     private boolean onGraphComputer = false;
     private GroupStepHelper.GroupMap<S, K, V> groupMap;
 
-    public GroupSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey) {
+    public GroupSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey, final boolean groupCount) {
         super(traversal);
         this.sideEffectKey = sideEffectKey;
         this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
+        if (this.groupCount = groupCount) {
+            this.valueReduceTraversal = this.integrateChild(__.count().asAdmin());
+            this.valueTraversal = this.integrateChild(__.identity().asAdmin());
+            this.reduceTraversal = this.integrateChild(__.count().asAdmin());
+        } else {
+            this.valueTraversal = this.integrateChild(__.identity().asAdmin());
+            this.reduceTraversal = this.integrateChild(__.fold().asAdmin());
+            this.valueReduceTraversal = this.integrateChild(__.fold().asAdmin());
+        }
+    }
+
+    @Override
+    public List<Traversal.Admin<?, ?>> getLocalChildren() {
+        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(4);
+        if (null != this.keyTraversal)
+            children.add((Traversal.Admin) this.keyTraversal);
+        children.add(this.valueReduceTraversal);
+        children.add(this.valueTraversal);
+        children.add(this.reduceTraversal);
+        return children;
     }
 
     @Override
@@ -79,6 +100,8 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
             this.keyTraversal = this.integrateChild(kvTraversal);
             this.state = 'v';
         } else if ('v' == this.state) {
+            if (this.groupCount)
+                throw new IllegalStateException("The key traversal for groupCount()-step have already been set: " + this);
             this.valueReduceTraversal = this.integrateChild(GroupStepHelper.convertValueTraversal(kvTraversal));
             final List<Traversal.Admin<?, ?>> splitTraversal = GroupStepHelper.splitOnBarrierStep(this.valueReduceTraversal);
             this.valueTraversal = this.integrateChild(splitTraversal.get(0));
@@ -90,6 +113,11 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
     }
 
     @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
+    }
+
+    @Override
     protected void sideEffect(final Traverser.Admin<S> traverser) {
         if (this.onGraphComputer) {      // OLAP
             final Map<K, Collection<?>> map = traverser.sideEffects(this.sideEffectKey);
@@ -106,6 +134,8 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
                 final Object object = traverser.sideEffects(this.sideEffectKey);
                 if (!(object instanceof GroupStepHelper.GroupMap))
                     traverser.sideEffects(this.sideEffectKey, this.groupMap = new GroupStepHelper.GroupMap<>((Map<K, V>) object));
+                else
+                    this.groupMap = (GroupStepHelper.GroupMap) object;
             }
             final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
             Traversal.Admin<S, V> traversal = this.groupMap.get(key);
@@ -139,22 +169,6 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
     }
 
     @Override
-    public List<Traversal.Admin<?,?>> getLocalChildren() {
-        final List<Traversal.Admin<?,?>> children = new ArrayList<>(4);
-        if (null != this.keyTraversal)
-            children.add((Traversal.Admin) this.keyTraversal);
-        children.add(this.valueReduceTraversal);
-        children.add(this.valueTraversal);
-        children.add(this.reduceTraversal);
-        return children;
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
-    }
-
-    @Override
     public GroupSideEffectStep<S, K, V> clone() {
         final GroupSideEffectStep<S, K, V> clone = (GroupSideEffectStep<S, K, V>) super.clone();
         if (null != this.keyTraversal)
@@ -170,6 +184,7 @@ public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implem
         int result = super.hashCode() ^ this.sideEffectKey.hashCode();
         if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
         result ^= this.valueReduceTraversal.hashCode();
+        result ^= Boolean.valueOf(this.groupCount).hashCode();
         return result;
     }