[JAVA] Diverses histoires déroutantes avec Map # computeIfAbsent

Map # computeIfAbsent est une méthode ajoutée dans Java8, et bien que cela fasse 5 ans, je la connaissais il y a environ un an.

V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

Si la valeur correspondant à key n'existe pas, mappingFunction est appelé et la valeur de retour est stockée dans Map et renvoyée.

ConcurrentHashMap Des questions se sont posées lors de la mise en œuvre du processus de mise en cache des données sur un système Web.

private Map<String, String> cache = new ConcurrentHashMap<>()

public String get(String id) {
  return cache.computeIfAbsent(key, key -> {
    if (/*Le fichier externe correspondant à la clé existe*/) {
      //Lire et renvoyer le fichier
      return readData;
    }
    //Il n'y a pas de fichier correspondant
    return null;
  });
}

Est-il correct de renvoyer null même si ConcurrentHashMap ne peut pas avoir null dans la valeur? J'ai donc essayé d'expérimenter le code de test.

Map<String, String> map = new ConcurrentHashMap<>();
String ret = map.computeIfAbsent("test", key -> null);
System.out.println(ret);

Le résultat de l'exécution ne faisait pas exception et la valeur de retour était nulle. C'est dans Javadoc Il a été écrit correctement. .. ..

Si la clé spécifiée n'est pas encore associée à une valeur, essayez de calculer cette valeur à l'aide de la fonction de mappage spécifiée et
S'il n'est pas nul, saisissez-le dans cette carte.

Kotlin Comme vous pouvez le voir, ce qui précède est écrit en Java, mais comme le développement du système en est également à ses débuts, lorsque j'ai réécrit le code sur Kotlin, une erreur de compilation s'est produite. La version de Kotlin est 1.3.31.

val cache = ConcurrentHashMap<String, String>()

fun get(id: String): String? {
  return cache.computeIfAbsent(id) {
    if (/*Le fichier externe correspondant à la clé existe*/) {
      //Lire et renvoyer le fichier
      return readData;
    }
    return null; //Erreur! Kotlin: Null can not be a value of a non-null type String
  }
}

Selon la référence API de Kotlin, Map.get

operator fun get(key: K): V?

Et V autorise null, mais la valeur de retour de mappingFunction semble rester V. Comme solution de contournement

val ret: String? = map.computeIfAbsent("test") { null!! }

Si vous ajoutez !! comme ceci, l'erreur de compilation sera résolue, mais kotlin.KotlinNullPointerException se produira lors de l'exécution. .. .. orz

Comme solution

val map = ConcurrentHashMap<String, String?>()
val ret: String? = map.computeIfAbsent("test") { null }

Je ne savais que ** déclarer V avec une tolérance nulle depuis le début **. Cependant, si je craignais que la valeur de retour de get ne soit un type étrange avec cela, cela n'existait pas comme une évidence, et je n'ai trouvé aucun inconvénient jusqu'à présent en le rendant String?, Alors est-ce la bonne réponse? Je vois.

Recommended Posts

Diverses histoires déroutantes avec Map # computeIfAbsent