首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java集合pack()方法

Java集合pack()方法
EN

Stack Overflow用户
提问于 2017-08-03 01:10:35
回答 4查看 322关注 0票数 5

使用Java流实现集合的pack()操作的好方法是什么?以下是我想要完成的任务:

代码语言:javascript
复制
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]]

或者,pack操作可以以(index、元素、count)的形式返回元组列表。

代码语言:javascript
复制
[(0, A, 2), (2, B, 2), (4, A, 1), (5, C, 2), (7, A, 3)]

目前,我以以下方式使用可变累加器实现了此功能:

代码语言:javascript
复制
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());
    }

}
EN

回答 4

Stack Overflow用户

发布于 2017-08-03 01:39:43

可以使用StreamEx折叠相邻元素。

代码语言:javascript
复制
List<List<String>> packs = StreamEx.of(items)
        .collapse(Object::equals, Collectors.toList())
        .collect(Collectors.toList());

输出:

代码语言:javascript
复制
[[A, A], [B, B], [A], [C, C], [A, A, A]]

JDoodle演示

我不确定StreamEx是否支持用索引折叠。

票数 4
EN

Stack Overflow用户

发布于 2017-08-03 02:38:34

正如@shmosel在他的回答中提到的,这可以由StreamEx来完成。

代码语言:javascript
复制
List<List<String>> packs = StreamEx.of(items).collapse(Object::equals, Collectors.toList()).toList();
System.out.println(packs);
// [[A, A], [B, B], [A], [C, C], [A, A, A]]

MutableInt idx = MutableInt.of(0);
List<Triple<Integer, String, Integer>> packs2 = StreamEx.of(items).collapse(Object::equals, Collectors.toList())
        .map(l -> Triple.of(idx.getAndAdd(l.size()), l.get(0), l.size())).toList();

System.out.println(packs2);
// [[0, A, 2], [2, B, 2], [4, A, 1], [5, C, 2], [7, A, 3]]

更新:刚刚发现,实际上,在StreamEx中有更简单的API可用于此操作:

代码语言:javascript
复制
packs = StreamEx.of(items).groupRuns(Object::equals).toList();
System.out.println(packs);

packs2 = StreamEx.of(items).runLengths().mapKeyValue((k, v) -> Triple.of(idx.getAndAdd(v.intValue()), k, v.intValue())).toList();
System.out.println(packs2);

太棒了!

票数 3
EN

Stack Overflow用户

发布于 2017-08-03 04:15:58

尝尝这个。

代码语言:javascript
复制
List<String> items = Arrays.asList("A", "A", "B", "B", "A", "C", "C", "A", "A", "A");
List<List<String>> result = items.stream()
    .collect(() -> new LinkedList<List<String>>(),
        (list, e) -> {
            if (list.isEmpty() || !list.getLast().contains(e))
                list.add(new LinkedList<>());
            list.getLast().add(e);
        },
        (a, b) -> {});
System.out.println(result);

结果

代码语言:javascript
复制
[[A, A], [B, B], [A], [C, C], [A, A, A]]

这不能用并行流处理。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45473229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档