请考虑以下代码段:
private List<User> getUsers() throws TasteException {
final int MAX_USERS = 100;
List<User> userList = new ArrayList<>(MAX_USERS);
dataModel.getUserIDs().forEachRemaining(userId -> {
if (userList.size() == 100) {
// stop
}
userList.add(new User(userId));
});
return userList;
}
break
或return
无效。我该怎么办?
答案 0 :(得分:5)
提前停止迭代的唯一方法是抛出异常。不建议使用控制流的异常,所以我会使用Stream.limit,.map和.collect:
private List<User> getUsers() throws TasteException {
final int MAX_USERS = 100;
return dataModel.getUserIDs()
.stream()
.limit(MAX_USERS)
.map(userId -> new User(userId))
.collect(Collectors.toList());
}
如果无法更改getUserIDs以返回Collection,您可以先转换为Spliterator:
private List<User> getUsers() throws TasteException {
final int MAX_USERS = 10;
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(dataModel.getUserIDs(), 0), false)
.limit(MAX_USERS)
.map(userId -> new User(userId))
.collect(Collectors.toList());
}
答案 1 :(得分:2)
考虑正确使用流,似乎你想要:
dataModel.getUserIDs().stream()
.limit(100)
.forEach(userId -> userList.add(new User(userId)));
这将获得前100个项目的流并对它们执行操作。由于我不知道dataModel.getUserIDs()
的签名,我无法给出更详细的答案。
答案 2 :(得分:2)
在进行任何密集操作之前,您可以'模拟'break;
在foreach lambda主体的开头添加一个if进行布尔检查
请注意,我使用final Map<Boolean>
来保存boolean
标志found
,因为这是在lambda外声明一个布尔'变量'的方法(你知道,它必须是' final')但是能够在循环中设置它的值
boolean containsSecret(Iterable<String> values) {
final Map<String, Boolean> scopedLambdaBooleans = new HashMap<String, Boolean>();
scopedLambdaBooleans.put("found", false);
values.forEach(s -> {
if (scopedLambdaBooleans.get("found")) {
return; //just the overhead of a boolean if but a continue before any iteration is very near to the break; performance
}
//Logger.getAnonymousLogger().info(s);
if (secret.equals(s)) {
scopedLambdaBooleans.put("found", true);
}
});
return scopedLambdaBooleans.get("found");
}
开销只是在任何迭代开始时的布尔if
检查
如果您因添加if check
而感到内疚,您可以补偿摆脱内部if
:
boolean containsSecretNoInternalIf(Iterable<String> values) {
final Map<String, Boolean> scopedLambdaBooleans = new HashMap<String, Boolean>();
scopedLambdaBooleans.put("found", false);
values.forEach(s -> {
if (scopedLambdaBooleans.get("found")) {
return; //just the overhead of a boolean if but a continue before any iteration is very near to the break; performance
}
Logger.getAnonymousLogger().info(s);
scopedLambdaBooleans.put("found", secret.equals(s));
});
return scopedLambdaBooleans.get("found");
}
无论如何,在发现之前的任何迭代中都在内存中写入一个布尔“位”,我不知道是否真的比'if'更好(如果在使用一点内存的.equals上检查'执行自己或直接cpu寄存器?嗯...在jvm上我们应该认为它像'堆栈与堆'并且是的,我认为现代jvm与JIT编译器堆栈有优化直接使用cpu寄存器)
答案 3 :(得分:1)
控制流程(中断,提前返回) - 在上面的forEach示例中,通过放置“return”可以实现传统的继续操作。 lambda中的陈述。但是,没有办法打破循环或从lambda中返回包含该方法的结果的值。例如:
final String secret = "foo";
boolean containsSecret(Iterable<String> values) {
values.forEach(s -> {
if (secret.equals(s)) {
??? // want to end the loop and return true, but can't
}
});
}
点击此处查看更多链接:http://www.techempower.com/blog/2013/03/26/everything-about-java-8/
答案 4 :(得分:0)
为了从Scanner实例的forEachRemaining中中断/退出,请在满足退出条件后如下关闭控制台输入。
scanner.forEachRemaining(s -> {
if(s.equals("exit")) {
try {
System.in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
parkingLot.execute(s.trim().split(" "));
});