Pourquoi serait java carte collector jeter une clé en double sur l'objet d'origine

Vic:

Lorsque vous exécutez le code suivant compilé sur 8 JDK l'exception est lancée

java.lang.IllegalStateException: La clé en double 1

ce qui indique que même si la nouvelle clé est censé être un objet différent d'un type différent, l'exception mentionne encore l'objet original.

List<Integer> ints = ImmutableList.of(1, 1);
Map<String, Integer> m = ints.stream()
    .collect(Collectors.toMap(intgr -> String.valueOf(intgr + 1), Function.identity()));

La fonction de mappage peut être arbitrairement des objets complexes et totalement différents finissent par être mis en correspondance avec la même clé, pourquoi choisir ce comportement d'exception?

Je veux dire, pourquoi l'exception levée est pas « clé en double 2 »?

Remarque: dans notre cas , la valeur d' origine qui a été mis en correspondance est une classe tierce partie sans la toStringmise en œuvre de sorte qu'il était impossible de savoir ce qui a causé la duplication.

Dean Xu:

Cela pourrait être un bug jdk. Je pense qu'il peut être résolu dans la version supérieure. (J'utilise 1.8_162)

Vous pouvez voir Collectors#throwingMerger.

private static <T> BinaryOperator<T> throwingMerger() {
    return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}

Alors que le paramètre d'entrée u, vest de venir Map#merge. Il est l'ancienne valeur et la nouvelle valeur. Il est donc 1, 1dans votre cas. Mais le message d'erreur est Duplicate key, il est tout à fait tort , car les deux uet vn'est pas clé , mais la valeur.

ÉDITER

jdk Vérifié 10, ce bug a été corrigé.

voir https://github.com/XDean/openjdk/blob/67672eec97164de10a9ca83ddbcef6b42816ed04/src/java.base/share/classes/java/util/stream/Collectors.java#L174

Maintenant Collectors.toMaputiliser sa propre fonction accumulate plutôt que d' utiliser Map.merge.

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=179833&siteId=1
conseillé
Classement