Search code examples
javacollectionsjava-8java-streamfold

Reducing a Collection in Java 8


I am wondering what is the cleanest , perhaps idiomatic, way to something like the following trivial example.

If I have an array (or list, etc) [1,1,1,2,3,5,5,9] I want to do a reduction, fold, of sorts, where consecutive numbers are added, leaving only one element.

So [1,1,1,2,3,5,5,9] would become [3,2,3,10,9].


A slightly more generalized case:

[object1, object2, object3, object4] where object1 and object2 have some combination of properties that would make it necessary to create a new object5 to replace both of them and the result would be [object5, object3, object4].

My actual use case is a bit more complicated, but the idea is similar in iterating over a list, somehow, but not reducing to a single atomic value.


Solution

  • The reduction is Stream API doesn't work this way. The point of the reduction (also called as fold) is to combine input elements into a single result.

    This is clearly not a suitable task for Stream API as long as the computation relies on the consecutive elements based on the equivalence.

    You want go for something like this*... which I have no idea to "convert" into Stream API.

    List<Integer> list = Arrays.asList(1,1,1,2,3,5,5,9);
    List<Integer> newList = new ArrayList<>();
    
    int i = 0;
    while (i < list.size()) {
        int current = list.get(i);
        int next = current;
        int sum = 0;
        int j = i;
        while (current == next) {
            j++;
            sum += next;
            if (j < list.size()) {
                next = list.get(j);
            } else break;
        }
        newList.add(sum);
        i = j;
    }
    
    // [3, 2, 3, 10, 9]
    System.out.println(newList);                  
    

    *This is clearly not the best solution in terms of performance and readability as long as I really suck in "LeetCode" problems solving. The idea is to demonstrate these solutions don't go well with Stream API.