web-dev-qa-db-fra.com

Hashmap ne fonctionne pas avec int, char

Duplicate possible:
Stockage des valeurs primitives dans un Java collection?

Dans Java lorsque j'utilise les éléments suivants: -

public HashMap<char, int> buildMap(String letters)
{
    HashMap<char, int> checkSum = new HashMap<char, int>();

    for ( int i = 0; i < letters.length(); ++i )
    {
        checkSum.put(letters.charAt(i), primes[i]);
    }

    return checkSum;
}

Je reçois des erreurs liées à des types inappropriés. J'ai résolu mon problème en utilisant Character et Integer au lieu de char et int, respectivement. Cependant, j'ai du mal à comprendre pourquoi HashMap ne parvient pas à gérer les types de données primitifs.

61
user277465

Les paramètres génériques peuvent uniquement se lier aux types de référence, pas aux types primitifs. Vous devez donc utiliser les types d'encapsuleurs correspondants. Essayez HashMap<Character, Integer> au lieu.

Cependant, j'ai du mal à comprendre pourquoi HashMap ne parvient pas à gérer les types de données primitifs.

Ceci est dû à type effacement . Java n'avait pas de génériques depuis le début, donc un HashMap<Character, Integer> est vraiment un HashMap<Object, Object>. Le compilateur effectue une série de vérifications supplémentaires et d'incantations implicites pour s'assurer que vous n'introduisez pas un type de valeur incorrect ou n'en sortez pas un type incorrect, mais au moment de l'exécution, il n'y a qu'une seule classe HashMap qui stocke les objets. .

D'autres langages "spécialisent" donc en C++, un vector<bool> est très différent d'un vector<my_class> en interne et ils ne partagent aucun commun vector<?> super-type. Java définit les choses de sorte qu'un List<T> est un List indépendamment de ce que T est destiné à la compatibilité ascendante avec code générique. Cette exigence de compatibilité ascendante selon laquelle il doit exister une seule classe d'implémentation pour toutes les paramétrisations d'un type générique empêche le type de spécialisation de modèle qui permettrait aux paramètres génériques de se lier à des primitives.

117
Mike Samuel

Les génériques ne peuvent pas utiliser de types primitifs sous la forme de mots-clés.

Utilisation

public HashMap<Character, Integer> buildMap(String letters)
{
    HashMap<Character, Integer> checkSum = new HashMap<Character, Integer>();

    for ( int i = 0; i < letters.length(); ++i )
    {
        checkSum.put(letters.charAt(i), primes[i]);
    }

    return checkSum;
}

Mise à jour: Avec Java 7 et versions ultérieures, vous pouvez utiliser l'opérateur Diamond.

HashMap<Character, Integer> checkSum = new HashMap<>();
13

Les génériques ne supportent que les types d'objet, pas les primitives. Contrairement aux modèles C++, les génériques n'impliquent pas de génération de code et il n'existe qu'un code HashMap, quel que soit le nombre de types génériques utilisés.

Trove4J contourne en générant à l'avance les collections sélectionnées pour utiliser des primitives et des supports TCharIntHashMap pouvant être encapsulés pour prendre en charge le Map<Character, Integer> si vous avez besoin.

TCharIntHashMap: Une implémentation de carte adressée ouverte pour les clés char et les valeurs int.

3
Peter Lawrey

Les hashmaps ne peuvent utiliser que classes, pas primitives. Ceci page de programmerinterview.com pourrait être utile pour vous guider dans la recherche de la réponse. Pour être honnête, je n'ai pas trouvé la réponse à ce problème en détail moi-même.

2

Vous ne pouvez pas mettre de types primitifs dans des collections. Cependant, vous pouvez les déclarer à l'aide de leurs wrappers d'objet correspondants tout en ajoutant les valeurs primitives, tant que la boxe le permet.

2
Dan D.

Les classes de collection génériques ne peuvent pas être utilisées avec des primitives. Utilisez plutôt les classes wrapper Character et Integer.

Map<Character , Integer > checkSum = new HashMap<Character, Integer>();

2
clinton

Generics peut être défini en utilisant Wrapper classes uniquement. Si vous ne souhaitez pas définir à l'aide de types Wrapper, vous pouvez utiliser la définition brute comme ci-dessous.

@SuppressWarnings("rawtypes")
public HashMap buildMap(String letters)
{
    HashMap checkSum = new HashMap();

    for ( int i = 0; i < letters.length(); ++i )
    {
       checkSum.put(letters.charAt(i), primes[i]);
    }
    return checkSum;
}

Ou définissez HashMap à l'aide de types d'encapsuleur et stockez les types primitifs. Les valeurs primitives seront promues dans leurs types wrapper.

public HashMap<Character, Integer> buildMap(String letters)
{
  HashMap<Character, Integer> checkSum = new HashMap<Character, Integer>();

  for ( int i = 0; i < letters.length(); ++i )
  {
    checkSum.put(letters.charAt(i), primes[i]);
  }
  return checkSum;
}
2
Yogendra Singh