Question: I have very big Stream of versioned documents ordered by document id and version.

E.g. Av1, Av2, Bv1, Cv1, Cv2

I have to convert this into another Stream whose records are aggregated by document id.

A[v1, v2], B[v1], C[v1, V2]

Can this be done without using `Collectors.groupBy()`? I don't want to use `groupBy()` because it will load all items in the stream into memory before grouping them. In theory, one need not load the whole stream in memory because it is ordered.

Answer: 
You can use [`groupRuns`](http://amaembo.github.io/streamex/javadoc/one/util/streamex/StreamEx.html#groupRuns-java.util.function.BiPredicate-) in the [StreamEx library](https://github.com/amaembo/streamex) for this:

```
class Document {
    public String id;
    public int version;
    public Document(String id, int version) {
        this.id = id;
        this.version = version;
    }
    public String toString() {
        return "Document{"+id+version+ "}";
    }
}

public class MyClass {
    private static List<Document> docs = asList(
        new Document("A", 1),
        new Document("A", 2),
        new Document("B", 1),
        new Document("C", 1),
        new Document("C", 2)
    );

    public static void main(String args[]) {
        StreamEx<List<Document>> groups = StreamEx.of(docs).groupRuns((l, r) -> l.id.equals(r.id));
        for (List<Document> grp: groups.collect(toList())) {
            out.println(grp);
        }
    }
}

```

which outputs:

> 
> [Document{A1}, Document{A2}]  
> 
>  [Document{B1}]  
> 
>  [Document{C1}, Document{C2}]
> 
> 
> 

I can't verify this doesn't consume the entire stream, but I cannot imagine why it would need to given what `groupRuns` is meant to do.
Would a `Map<String, Stream<String>>` help you with what you need ? 

> 
> A - v1, v2   
>  
>  B - v1  
> 
>  C - v1, v2   
> 
> 
> 
> 

```
 String[] docs = { "Av1", "Av2", "Bv1", "Cv1", "Cv2"};
 Map<String, Stream<String>> map = Stream.<String>of(docs).
         map(s ->s.substring(0, 1)).distinct().                      //leave only A B C
            collect(Collectors.toMap( s1 -> s1,                      //A B C as keys
                                      s1 ->Stream.<String>of(docs).  //value is filtered stream of docs
                                        filter(s2 -> s1.substring(0, 1).
                                          equals(s2.substring(0, 1)) ).
                                            map(s3 -> s3.substring(1, s3.length())) //trim A B C
                                     ));        

```