java - 限制一个流,看看是否有挂起的元素

标签 java loops iterator java-8 java-stream

我有以下代码要转换为 Java 8 流:

public ReleaseResult releaseReources() {
    List<String> releasedNames = new ArrayList<>();

    Stream<SomeResource> stream = this.someResources();

    Iterator<SomeResource> it = stream.iterator();
    while (it.hasNext() && releasedNames.size() < MAX_TO_RELEASE) {
        SomeResource resource = it.next();
        if (!resource.isTaken()) {
            resource.release();
            releasedNames.add(resource.getName());
        }
    }

    return new ReleaseResult(releasedNames, it.hasNext(), MAX_TO_RELEASE);
}

方法someResources()返回 Stream<SomeResource>ReleaseResult类如下:

public class ReleaseResult {

    private int releasedCount;

    private List<String> releasedNames;

    private boolean hasMoreItems;

    private int releaseLimit;

    public ReleaseResult(List<String> releasedNames, 
        boolean hasMoreItems, int releaseLimit) {

        this.releasedNames = releasedNames;
        this.releasedCount = releasedNames.size();
        this.hasMoreItems = hasMoreItems;
        this.releaseLimit = releaseLimit;
    }

    // getters & setters
}

到目前为止我的尝试:

public ReleaseResult releaseReources() {

    List<String> releasedNames = this.someResources()
        .filter(resource -> !resource.isTaken())
        .limit(MAX_TO_RELEASE)
        .peek(SomeResource::release)
        .map(SomeResource::getName)
        .collect(Collectors.toList());

    return new ReleasedResult(releasedNames, ???, MAX_TO_RELEASE);
}

问题是我无法找到一种方法来了解是否有待处理的资源。我想过使用 releasedNames.size() == MAX_TO_RELEASE ,但这没有考虑资源流恰好 MAX_TO_RELEASE 的情况。元素。

有没有办法对 Java 8 流执行相同的操作?

注意:我不是在寻找像“你不必用流做所有事情”“使用循环和迭代器就可以”这样的答案“。如果使用迭代器和循环是唯一的方法或最好的方法,我没意见。只是我想知道是否有一种简单的方法可以做到这一点。

最佳答案

既然你不想听到你不需要所有的流,循环和迭代器很好,让我们通过展示一个干净的解决方案来证明它,而不是依赖于 peek:

public ReleaseResult releaseReources() {
    return this.someResources()
        .filter(resource -> !resource.isTaken())
        .limit(MAX_TO_RELEASE+1)
        .collect(
            () -> new ReleaseResult(new ArrayList<>(), false, MAX_TO_RELEASE),
            (result, resource) -> {
                List<String> names = result.getReleasedNames();
                if(names.size() == MAX_TO_RELEASE) result.setHasMoreItems(true);
                else {
                    resource.release();
                    names.add(resource.getName());
                }
            },
            (r1, r2) -> {
                List<String> names = r1.getReleasedNames();
                names.addAll(r2.getReleasedNames());
                if(names.size() > MAX_TO_RELEASE) {
                    r1.setHasMoreItems(true);
                    names.remove(MAX_TO_RELEASE);
                }
            }
        );
}

这假定 //getters & setters 包含 ReleaseResult 的所有非 final 字段的 getters 和 setters。 getReleasedNames() 通过引用返回列表。否则,您将不得不重写它以提供一个专门的 Collector 具有对 ReleaseResult 的特殊非公共(public)访问权限(实现另一种构建器类型或临时存储将是不必要的复杂化,它看起来就像 ReleaseResult 已经完全针对该用例设计了)。

我们可以得出结论,对于任何不适合流的内部操作的非平凡循环代码,您可以找到一个收集器解决方案,其功能基本上与 accumulator 函数中的循环相同,但是遭受总是必须提供 combiner 功能的要求。好的,在这种情况下,我们可以在前面加上一个 filter(...).limit(...) 这样还不错...

我刚刚注意到,如果您敢于将其与并行流一起使用,则需要一种方法来扭转释放组合器中最后一个元素的效果,以防组合大小超过 MAX_TO_RELEASE。通常,限制和并行处理永远不会发挥很好的作用。

关于java - 限制一个流,看看是否有挂起的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36041475/

相关文章:

java - 如何接收 convertAndSend 发送的内容?

Java ArrayList,抽象类返回ArrayList的访问方法

java - 消费者构造函数陷阱

python - 使用类级别变量停止 while 循环

c++ - STL 迭代器的语法是如何实现的?

java - 单击后重命名按钮 - Java JButton

c - 用于查找素数的埃拉托色尼筛算法的上限使程序停止工作

java - 绘制组件会重复自身,无需任何用户交互

c++ - 为什么 void* 不是迭代器类型?

java - 线程 "main"java.util.ConcurrentModificationException 中的异常