Java collection pack() method

Viewed 312

What would be a good way to implement the pack() operation of a collection using Java stream? Here is what I'd like to accomplish:

List<String> items = Arrays.asList("A", "A", "B", "B", "A", "C", "C", "A", "A", "A");
List<List<String>> packs = items.stream().pack();
// packs:  [[A,A],[B,B],[A],[C,C],[A,A,A]]

Alternatively, the pack operation could return a list of tuples in the form of (index, element, count):

[(0, A, 2), (2, B, 2), (4, A, 1), (5, C, 2), (7, A, 3)]

Currently I implemented this using a mutable accumulator in the following fashion:

Packer<String> packer = new Packer<>();
items.stream().forEach(packer);
List<Triple<Integer, T, Integer>> packs = packer.get();

public class Packer<T> implements Consumer<T>, Supplier<List<Triple<Integer, T, Integer>>>
{
    private List<Triple<Integer, T, AtomicInteger>> result = new ArrayList<>();
    private Optional<Triple<Integer, T, AtomicInteger>> currentElement = Optional.empty();
    private int count = 0;

    @Override
    public void accept(T t)
    {
        if (currentElement.isPresent() && currentElement.get().getMiddle().equals(t))
        {
            currentElement.get().getRight().incrementAndGet();
        }
        else
        {
            currentElement = Optional.of(Triple.of(count, t, new AtomicInteger(1)));
            result.add(currentElement.get());
        }
        count++;
    }

    @Override
    public List<Triple<Integer, T, Integer>> get()
    {
        return result.stream().map(x -> Triple.of(x.getLeft(), x.getMiddle(), x.getRight().get())).collect(Collectors.toList());
    }

}
4 Answers
Related