2009-05-24 6 views
6

J'ai une liste de fichiers. Je voudrais parcourir et compter le nombre de fichiers ayant la même taille. le problème est avec la taille de fichier qui est une longue, comme nous le savons, hashmap ne prendra qu'un objet et pas une primitive. Donc, en utilisant new Long(filesize), je l'ai mis dans le hashmap. Au lieu d'avoir une paire de (filesize, count), j'ai une liste de (filesize, 1) en raison du fait que chaque obj Long est unique.Conserver une paire de primitives dans un Java HashMap

Comment puis-je construire cet accumulateur?

une solution pour 1.4.2?

Répondre

15

Vous faites simplement cette façon:

Map<Long, Integer> count = new HashMap<Long, Integer>(); 
for (File file : files) { 
    long size = file.getTotalSpace(); 
    Integer n = count.get(size); 
    if (n == null) { 
    count.put(size, 1); 
    } else { 
    count.put(size, n + 1); 
    } 
} 

Il y a quelques auto-boxing et unboxing se passe ici.

3

ou vous pouvez utiliser AtomicInteger comme entier mutable.

Map<Long, AtomicInteger> count = new HashMap<Long, AtomicInteger>(); 
for (File file : files) { 
    long size = file.length(); // getTotalSpace() get the space consumed (e.g. a multiple of 8K) rather the actual file size. 
    AtomicInteger n = count.get(size); 
    if (n == null) { 
    count.put(size, new AtomicInteger(1)); 
    } else { 
    n.getAndIncrement(); 
    } 
} 
7

Au lieu d'utiliser new Long(size), vous devez utiliser Long.valueOf(size). Cela retournera la même référence longue qui est mise en cache en interne, et devrait également augmenter les performances (pas qu'elle sera visible sauf si vous effectuez des millions de ces opérations new Long()).

ps. fonctionne uniquement pour Java 1.5 ou supérieur

+0

AFAICT dans 1.6 met en cache Long.valueOf que les 256 positions longues qui chevauchent zéro . Toute valeur supérieure à 128 ne sera pas mise en cache, de même que les valeurs inférieures à -127. –

+0

pour 1.6 (pas 1.5 ou moins afaik) vous pouvez changer ce comportement en mettant -XX: AutoBoxCacheMax = 1000 (voir http://www.javaspecialists.eu/archive/Issue191.html) - si votre application est ralentie par de telles opérations déjà, alors je doute qu'il y ait un problème algorithmique là-bas ... – Chii

1

Expansion de ce que écrit Cletus.

Sa solution est correcte, sauf qu'il ne stocke que chaque taille de fichier que vous rencontrez et le nombre de fichiers qui ont cette taille. Si jamais vous voulez savoir quels sont ces fichiers, cette structure de données vous sera inutile alors je ne pense pas que la solution de Cletus soit complète. Au lieu de cela, je ferais alors

Map<Long, Collection<File>> count = new HashMap<Long, Collection<File>>(); 
for (File file : files) { 
long size = file.getTotalSpace(); 
Collection<File> c = count.get(size); 
if (c == null) { 
    c = new ArrayList<File>(); //or whatever collection you feel comfortable with 
    count.put(size, c); 
} 
    c.add(file); 
} 

vous pouvez obtenir le nombre de fichiers avec c.size() et vous pouvez parcourir tous les fichiers avec ce nombre facilement sans avoir à exécuter cette procédure.

+1

Vous oubliez de mettre l'arraylist dans la carte. –

+0

merci! haha, j'ai tendance à oublier ces choses et elles reviennent me mordre dans le cul. – ldog

+0

solution utile, bien que la solution de Cletus est plus proche de ce dont j'ai besoin. – zeroin23

1

Je pense qu'il y a plus à cela, et nous aurons besoin de plus de détails de votre part. Je suppose que vous savez qu'il y a certainement plus d'un fichier d'une taille donnée, sinon je vérifie d'abord que c'est le cas. Pour tout ce que vous savez, vous avez simplement beaucoup de fichiers avec des tailles de fichiers uniques.

Vous avez dit:

... en raison du fait que chaque long obj est unique.

Je ne pense pas que ce soit le problème. Bien que cela puisse être vrai en fonction de la façon dont vous instanciez les Longs, cela ne devrait pas empêcher HashMaps de se comporter comme vous le souhaitez. Tant que les deux objets clés renvoient la même valeur hashCode() et que la méthode equals() indique qu'ils sont égaux, votre HashMap ne créera pas d'autre entrée pour cela. En fait, il ne devrait pas être possible de voir "une liste de (filesize, 1)" avec les mêmes valeurs de taille de fichier (sauf si vous avez écrit votre propre Long et que vous n'avez pas implémenté hashCode()/equals() correctement). Cela dit, le code de Cletus devrait fonctionner si vous utilisez Java 5 ou plus, si vous utilisez Java 1.4 ou moins, vous devrez soit faire votre propre boxing/unboxing manuellement, soit regarder dans Apache Commons Collections .Voici la version pré-Java 5 de l'exemple de Cletus:

Map count = new HashMap(); 
for (Iterator filesIter = files.iterator(); filesIter.hasNext();) { 
    File file = (File)filesIter.next(); 
    long size = file.getTotalSpace(); 
    Integer n = count.get(size); 
    if (n == null) { 
    count.put(size, Integer.valueOf(1)); 
    } else { 
    count.put(size, Integer.valueOf(n.intValue() + 1)); 
    } 
} 
+0

il est arrivé sur une machine jdk1.4.2 ... – zeroin23

Questions connexes