LinkedHashMap entrySet的顺序未保存在流中(Android) [英] LinkedHashMap entrySet's order not being preserved in a stream (Android)

查看:120
本文介绍了LinkedHashMap entrySet的顺序未保存在流中(Android)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为注册屏幕创建一个非常简单的表单验证实用程序,并且我遇到了一些关于 LinkedHashMap 的意外行为以及从其 entrySet

I'm creating a very simple form validation utility for a sign up screen, and I'm running into some unexpected behavior concerning LinkedHashMap and a stream created from its entrySet.

我将验证结果存储在 LinkedHashMap ,使用以下语句排序:

I'm storing validation results in a LinkedHashMap, with the following ordering of statements:

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循环并省略有效结果,无效结果按以下顺序显示:

One particular iteration yields all of the above fields invalid except for "confirm password". Using a simple for loop over the entry set and omitting valid results, the invalid results appear in the following order:


  • 电子邮件

  • 用户名

  • 生日

  • 密码

  • Email
  • Username
  • Birthday
  • Password

然后我尝试使用Android上可用的Stream API子集(目标版本25,最小值为19,因此缺少 Collectors.toMap()):

I then attempted to make use of the subset of Stream API's available on Android (targeting version 25 with a min of 19, hence the lack of 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;
}

但该代码产生以下顺序:

But that code yields the following order:


  • 生日

  • 密码

  • 用户名

  • 电子邮件

  • Birthday
  • Password
  • Username
  • Email

这里究竟发生了什么,为什么流的结果不符合的插入顺序LinkedHashMap的?请注意,如果我用 forEach 换出 forEachOrdered ,它仍然没有插入订单。

What exactly is happening here, why is the result of the stream not honoring the insertion order of the LinkedHashMap? Note that if I swap out forEachOrdered with forEach, it's still not insertion ordered.

推荐答案

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

This behavior is a known bug in Android's 7.0 / 7.1 implementation of LinkedHashMap.

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

The LinkedHashMap's collection views' spliterators for entrySet, values and keySet correctly report that they are ORDERED but actually they aren't because the spliterator implementation of the parent class (HashMap) is used internally.

此行为已被记录在案中那里也提出了Javadoc和变通方法。

This behavior has already been documented in the Javadoc and workarounds are also proposed there.

修复已于2016-08-16提交d将出现在下一个Android版本中。

The fix has been commited on 2016-08-16 and will appear in the next Android release.

澄清:Google在2017-01开始时就意识到了这个错误,所以上面提到的修复是偶然的固定。如果他们之前已经知道这个问题,那么分辨率将包含在7.1

For clarification: Google became aware of this bug at first in 2017-01, so the "fix" mentioned above was an accidental fix. If they had known about this problem earlier, the resolution would have been included in 7.1

这篇关于LinkedHashMap entrySet的顺序未保存在流中(Android)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆