我有以下代码要转换为 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/