我正在为注册屏幕创建一个非常简单的表单验证实用程序,并且我遇到了一些关于以下方面的意外行为LinkedHashMap
以及从其创建的流entrySet
.
我将验证结果存储在LinkedHashMap
,语句顺序如下:
Map<ValidationResult.SignUpField, Boolean> fieldStatuses = new LinkedHashMap<>();
fieldStatuses.put(EMAIL, isValidEmail(emailAddress));
fieldStatuses.put(USERNAME, isValidUsername(username));
fieldStatuses.put(BIRTHDAY, isValidBirthday(birthday));
fieldStatuses.put(PASSWORD, isValidPassword(password));
fieldStatuses.put(CONFIRM_PASSWORD, password.equals(confirmedPassword));
List<ValidationEntry> invalidFields = aggregateInvalidFields(fieldStatuses);
一次特定的迭代会导致除“确认密码”之外的所有上述字段均无效。对条目集使用简单的 for 循环并忽略有效结果,无效结果按以下顺序出现:
- Email
- Username
- Birthday
- Password
然后,我尝试利用 Android 上可用的 Stream API 子集(目标版本 25,最小值为 19,因此缺少Collectors.toMap()
):
private static List<ValidationEntry> aggregateInvalidFields(Map<ValidationResult.SignUpField, Boolean> fields) {
List<ValidationEntry> invalidFields = new ArrayList<>();
fields.entrySet()
.stream()
.filter(entry -> !entry.getValue())
.forEachOrdered(entry -> {
ValidationResult.SignUpField field = entry.getKey();
invalidFields.add(new ValidationEntry(field, lookUpErrorCode(field)));
});
return invalidFields;
}
但该代码产生以下顺序:
- Birthday
- Password
- Username
- Email
这里究竟发生了什么,为什么流的结果不遵守插入顺序LinkedHashMap
?请注意,如果我换出forEachOrdered
with forEach
,它仍然没有插入顺序。