方法是
private List<HighWay> getWillSave(List<HighWay> total,
HighWayRepository repository) {
List<HighWay> willSave = new ArrayList<HighWay>();
int lastSaved = total.size() - 1;
while (lastSaved >= 0
&& repository.exists(total.get(lastSaved).getId())) {
lastSaved--;
}
willSave.addAll(total.subList(0, ++lastSaved));
return willSave;
}
现在我尝试改变这样的流,我不知道改变是否正确:
private List<HighWay> getWillSave(Stream<HighWay> notDealItem,
HighWayRepository repository) {
List<HighWay> willSave = new ArrayList<HighWay>();
long lastSaved = notDealItem.count()-1;
while (lastSaved >= 0
&& repository.exists(notDealItem.skip(lastSaved-1).findFirst().get().getId())) {
lastSaved--;
}
willSave.addAll(notDealItem.collect(Collectors.toList()).subList(0, (int)(++lastSaved)));
return willSave;
}
但抛出了异常:
java.lang.IllegalStateException:stream已被操作 或关闭
我知道流只能消耗一次。而count和get方法都是消费者的方式。但我真的想知道计数并调用get方法。
如何避免异常并解决问题?
我应该以某种方式重构代码吗?
答案 0 :(得分:0)
嗯,我想你可以做那样的事......但与我们用真正的功能语言做的事情相比,这是非常不优雅的:
private List<HighWay> getWillSave(List<HighWay> total, HighWayRepository repository) {
List<HighWay> willSave = new ArrayList<HighWay>();
int size = total.size();
int index =
IntStream.range(0,size)
.mapToObj(i -> new Pair<>(i,size - i - 1))
.filter(p -> !repository.exists(p.getValue().getId()))
.findFirst()
.orElseGet(() -> new Pair<>(0,null)).getKey();
return total.subList(0,index);
}
答案 1 :(得分:0)
如果我理解您的代码的逻辑,您希望返回列表/流中的所有项目,直到您处于其余部分未通过测试repository.exists
的位置。那是对的吗?如果是这样,那么可以使用自定义收集器来实现:
class MyCollector {
private List<Highway> acceptedList = new ArrayList<>();
private List<Highway> currentList = new ArrayList<>();
public void accept(Highway highway) {
if (repostitory.exists(highway.getId())) {
acceptedList.addAll(currentList);
acceptedList.add(highway);
currentList.clear();
} else {
currentList.add(highway);
}
}
public Stream<Highway> stream() {
return acceptedList.stream();
}
}
我希望它清楚如何运作:如果项目未通过测试,则将它们放入临时列表,直到找到通过的项目。对于最终系列的失败项目,它们永远不会被放回到最终列表中。为简单起见,我已经跳过了合并器。
然后可以按照以下方式将其应用于您的高速公路流:
highwayStream()
.collect(MyCollector::new, MyCollector::accept, null)
.stream()
如果您确实需要返回.collect(Collectors.toList())
而不是其他信息流,则可以执行任何操作,包括List
。
提供此解决方案后,让我说我不相信流应该用于各种目的。它们最适合于相当独立地执行项目的情况。在您的情况下,最终列表非常依赖于其他项目。
更直接的解决方案可能是:
List<Highway> filteredList = new ArrayList(originalList);
int i = filteredList.size() - 1;
while (i >= 0 && repository.exists(filteredList.get(i).getId()))
filteredList.remove(i--);
return filteredList;