package com.tinkerpop.gremlin.process;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 */
public class Path {

    protected List<String> asLabels = new ArrayList<>();
    protected List<Object> objects = new ArrayList<>();

    public Path(final Object... asObjects) {
        if (asObjects.length % 2 != 0)
            throw new IllegalArgumentException("The provided array must be a multiple of two");
        for (int i = 0; i < asObjects.length; i = i + 2) {
            this.asLabels.add((String) asObjects[i]);
            this.objects.add(asObjects[i + 1]);
        }
    }

    public int size() {
        return this.objects.size();
    }

    public void add(final String as, final Object object) {
        this.asLabels.add(as);
        this.objects.add(object);
    }

    public void add(final Path path) {
        this.asLabels.addAll(path.asLabels);
        this.objects.addAll(path.objects);
    }

    public <T> T get(final String as) {
        for (int i = 0; i < this.asLabels.size(); i++) {
            if (this.asLabels.get(i).equals(as))
                return (T) this.objects.get(i);
        }
        throw new IllegalArgumentException("The as-step does not exist: " + as);
    }

    public <T> T get(final int index) {
        return (T) this.objects.get(index);
    }

    public List<String> getAsLabels() {
        return new ArrayList<>(this.asLabels);
    }

    public void renameLastStep(final String as) {
        this.asLabels.set(this.asLabels.size() - 1, as);
    }

    public boolean isSimple() {
        return new LinkedHashSet<>(this.objects).size() == this.objects.size();
    }

    public void forEach(final Consumer<Object> consumer) {
        this.objects.forEach(consumer);
    }

    public void forEach(final BiConsumer<String, Object> consumer) {
        for (int i = 0; i < this.size(); i++) {
            consumer.accept(this.asLabels.get(i), this.objects.get(i));
        }
    }

    public Path subset(final String... asLabels) {
        final Path path = new Path();
        this.forEach((as, object) -> {
            if (Stream.of(asLabels).anyMatch(as::equals))
                path.add(as, object);
        });
        return path;
    }

    public String toString() {
        return this.objects.toString();
    }
}

@@ -33,16 +33,45 @@
 ocess;%0A%0A
+import org.javatuples.Pair;%0A%0A
 import j
@@ -211,32 +211,67 @@
 ction.Consumer;%0A
+import java.util.stream.IntStream;%0A
 import java.util
@@ -2193,32 +2193,203 @@
        %7D%0A    %7D%0A%0A
+    public Stream%3CPair%3CString, Object%3E%3E stream()%7B%0A        return IntStream.range(0, this.size()).mapToObj(i-%3EPair.with(this.asLabels.get(i), this.objects.get(i)));%0A    %7D%0A%0A
     public Path 

Add stream function to Path class.