簡體   English   中英

LinkedHashMap entrySet的順序未保存在流中(Android)

[英]LinkedHashMap entrySet's order not being preserved in a stream (Android)

我正在為注冊屏幕創建一個非常簡單的表單驗證實用程序,我遇到了一些關於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的插入順序? 請注意,如果我用forEach換出forEachOrdered ,它仍然沒有按順序插入。

此行為是Android的LinkedHashMap 7.0 / 7.1實現中的已知錯誤。

LinkedHashMap的集合視圖的entrySetvalueskeySet的分裂器正確地報告它們是ORDERED但實際上它們不是因為父類(HashMap)的spliterator實現是在內部使用的。

這種行為已經記錄在Javadoc中,並且在那里也提出了變通方法。

修復程序已於2016-08-16提交,並將在下一個Android版本中出現。

澄清一下:谷歌最初在2017-01發現了這個錯誤,所以上面提到的“修復”是一個偶然的修復。 如果他們之前已經知道這個問題,那么該決議將包含在7.1中

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM