2010-06-07 20 views
5

L'exécution de ce code:Java HashSet et type de données Court, incompatibilité?

public class SomeSet { 

    public static void main(String[] args) { 

     Set<Short> s = new HashSet<Short>(); 

     for (short i = 0; i < 100; i++) { 

      s.add(i); 

      s.remove(i - 1); 

     } 

     System.out.println(s.size()); 

    } 

} 

imprimera la valeur 100.

Pourquoi faut-il imprimer cette valeur?

+1

comme quoi, vous voulez que nous l'essayions ??? – pgras

Répondre

10
s.remove(i - 1); 

La ligne ci-dessus tentera de supprimer Integer objets du jeu, parce que tous les calculs entiers en Java ont int (ou long) résultats. Puisque l'ensemble contient Short objets, la méthode remove() n'aura aucun effet.

Ceci (et des problèmes similaires) est la principale raison pour laquelle vous ne devriez presque jamais utiliser short (et, plus encore, Short). L'utilisation d'une implémentation Set pour contenir des nombres autoboxés entraîne une surcharge massive (facilement de 1000%), il est donc inutile d'essayer d'économiser de l'espace en utilisant Short au lieu de Integer.

+0

... ou 'float' ou' double' ;-) –

6

Le problème est que remove(i-1) appelle la méthode remove avec un objet Integer, puisque i-1 est de type int (qui obtient une auto-Integer boîte en).

Pour vous assurer que vous appelez remove avec une utilisation d'objets Short ceci:

s.remove((short) (i - 1)); 
+0

Ou plus explicitement s.remove (Short.valueOf (i-1)); –

+0

@Steve: qui ne serait pas compilé car vous auriez aussi besoin d'une distribution explicite. Rendre plus explicite mais aussi plus verbeux. –

0

Le type de i - 1 est int, de sorte qu'il devient autoboxed à un nombre entier.

Normalement, vous vous attendez à une collection générique pour vous empêcher d'effectuer des opérations qui ont des arguments du mauvais type, mais l'interface à Set<E> est un peu lâche.

Parce que la méthode remove de Set<E> prend un Object plutôt que d'un E, le compilateur ne vous avertit pas que vous supprimez un type différent de ce que l'ensemble contient.

Pour le forcer à être Short, attribuez la valeur numérique à (short). (Coulée à (Short) n'est pas autorisé, et vous auriez à jeter la valeur numérique à utiliser Short.valueOf)

0

Notez que la méthode add est boolean add(E o) génériquement tapé donc dans votre cas de définir la méthode d'ajout prendra un court, alors que la méthode remove n'est pas génériquement typée boolean remove(Object o) donc i - 1 autoboxes à un entier. Pour toute valeur de i new Short(i).equals(new Integer(i)) sera toujours faux.

Notez que si vous essayez s.add(i - 1); vous obtiendrez une erreur de compilation car i - 1 devient une instance de Integer et les types Integer et Short ne correspondent pas.