2009-05-24 8 views
6

Ich habe eine Liste von Dateien. Ich möchte die Anzahl der Dateien mit der gleichen Größe durchgehen und zählen. das Problem ist mit der Dateigröße, die eine lange ist, wie wir wissen, hashmap wird nur ein Objekt und nicht ein primitiv aufnehmen. Also benutze ich new Long(filesize), ich lege es in die hashmap. anstatt ein Paar von (Dateigröße, Anzahl) zu bekommen, habe ich eine Liste von (Dateigröße, 1) aufgrund der Tatsache, dass jedes Long Obj ist einzigartig.Halten Sie ein Paar von Primitiven in einem Java HashMap

Wie baue ich diesen Akku?

eine beliebige Lösung für 1.4.2?

Antwort

15

Sie tun es einfach so:

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); 
    } 
} 

Es gibt einige auto-boxing und Unboxing hier los ist.

3

oder Sie könnten AtomicInteger als eine veränderbare Ganzzahl verwenden.

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

Statt new Long(size) verwenden, sollten Sie Long.valueOf(size) verwenden. das wird die gleiche lange Referenz zurückgeben, die intern zwischengespeichert wird, und sollte auch die Leistung steigern (nicht, dass es sichtbar sein wird, wenn Sie Millionen dieser new Long()-Operationen ausführen).

ps. funktioniert nur für Java 1.5 oder höher

+0

AFAICT in 1,6 Long.valueOf nur speichert die 256 Long-Positionen, die Null spreizen . Alles, was höher als 128 ist, wird nicht zwischengespeichert, ebenso Werte unter -127. –

+0

für 1.6 (nicht 1.5 oder unter afaik) können Sie dieses Verhalten ändern, indem Sie -XX: AutoBoxCacheMax = 1000 setzen (siehe http://www.javaspecialists.eu/archive/Issue191.html) - wenn Ihre App verlangsamt wird Solche Operationen schon, dann vermute ich, dass es dort ein algorithmisches Problem gibt ... – Chii

1

Erweiterung auf was Cletus schrieb.

Seine Lösung ist in Ordnung, außer es speichert nur jede Dateigröße, die Sie finden, und die Anzahl der Dateien, die diese Größe haben. Wenn Sie jemals wissen wollen, welche Dateien das sind, wird diese Datenstruktur für Sie nutzlos sein, also glaube ich nicht, dass die Lösung von cetus vollständig ist. Stattdessen würde ich

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); 
} 

tun, dann können Sie die Anzahl der Dateien mit c.size() und Sie können mit dieser Nummer einfach durch alle Dateien durchlaufen, ohne sich erneut um dieses Verfahren ausführen zu müssen.

+1

Sie vergessen, die Arraylist in die Karte zu legen. –

+0

danke! haha, ich neige dazu, diese Dinge zu vergessen und sie kommen zurück, um mich in den Arsch zu beißen. – ldog

+0

nützliche Lösung, obwohl Cletus Lösung ist näher, was ich brauche. – zeroin23

1

Ich denke, es gibt mehr dazu, und wir brauchen mehr Details von Ihnen. Ich nehme an, Sie wissen, dass es definitiv mehr als eine Datei einer bestimmten Größe gibt, sonst würde ich zuerst überprüfen, ob das der Fall ist. Nach allem, was Sie wissen, haben Sie einfach eine Menge Dateien mit eindeutigen Dateigrößen.

Sie erwähnt:

... aufgrund der Tatsache, dass jede Lang obj einzigartig ist.

Ich glaube nicht, dass dies das Problem ist. Auch wenn dies abhängig davon sein mag, wie Sie die Longs instanziieren, sollte dies nicht verhindern, dass sich HashMaps so verhält, wie Sie es möchten. Solange die beiden Schlüsselobjekte denselben hashCode() - Wert zurückgeben und die equals() -Methode angibt, dass sie gleich sind, erstellt Ihre HashMap keinen weiteren Eintrag für sie. Tatsächlich sollte es Ihnen nicht möglich sein, "eine Liste von (Dateigröße, 1)" mit den gleichen Dateigrößenwerten zu sehen (es sei denn, Sie haben Ihre eigene Long geschrieben und HashCode()/equals() korrekt implementiert).

Das heißt, Cletus' Code sollte funktionieren, wenn Sie mit Java 5 oder höher, wenn Sie verwenden sind Java 1.4 oder unten, werden Sie müssen entweder manuell Ihre eigenen Boxen/Unboxing tun, oder schauen Sie in Apache Commons Collections .Hier ist die Pre-Java-5-Version von Cletus' Beispiel:

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

ist es passiert auf einer jdk1.4.2 Maschine ... – zeroin23