【问题标题】:LinkedHashMap entrySet's order not being preserved in a stream (Android)LinkedHashMap entrySet的顺序未保留在流中(Android)
【发布时间】:2017-03-10 06:07:21
【问题描述】:

我正在为注册屏幕创建一个非常简单的表单验证实用程序,但我遇到了一些关于 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 循环并省略有效结果,无效结果按以下顺序出现:

  • 电子邮件
  • 用户名
  • 生日
  • 密码

然后我尝试使用 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;
}

但该代码产生以下顺序:

  • 生日
  • 密码
  • 用户名
  • 电子邮件

这里到底发生了什么,为什么流的结果不符合LinkedHashMap 的插入顺序?请注意,如果我将forEachOrdered 换成forEach,它仍然不是插入顺序。

【问题讨论】:

  • 你能显示你的插入代码吗?
  • 确定,现在更新
  • 什么是invalidFields?
  • 那你为什么不使用EnumMap?
  • 你能试着把它减少到minimal reproducible example吗?很难知道你是否遗漏了一些重要的东西。

标签: java android java-stream linkedhashmap


【解决方案1】:

此行为是 Android 7.0 / 7.1 的 LinkedHashMap 实现中的一个已知错误。

entrySet、values 和 keySet 的 LinkedHashMap 集合视图的拆分器正确报告它们是 ORDERED,但实际上它们不是因为在内部使用了父类 (HashMap) 的拆分器实现。

此行为已在 Javadoc 中为 documented,并且在那里也提出了解决方法。

fix 已于 2016 年 8 月 16 日提交,并将出现在下一个 Android 版本中。

澄清一下:Google 最初是在 2017 年 1 月发现这个错误的,所以上面提到的“修复”是一个意外修复。如果他们早点知道这个问题,该解决方案就会包含在 7.1 中

【讨论】:

  • 所以我没疯!感谢您的洞察力。
猜你喜欢
  • 2010-11-14
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多