2009-05-24 14 views
6

У меня есть список файлов. Я бы хотел просмотреть и сохранить количество файлов с одинаковым размером. проблема связана с размером файла, который является длинным, как мы знаем, hashmap будет принимать только объект, а не примитив. Поэтому, используя new Long(filesize), я помещаю его в hashmap. вместо того, чтобы получить пару (filesize, count), я получил список (filesize, 1) из-за того, что каждый Long obj уникален.Сохранение пары примитивов в Java HashMap

Как я могу построить этот аккумулятор?

любое решение для 1.4.2?

ответ

15

Вы просто сделать это таким образом:

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

Там есть некоторые auto-boxing и распаковка происходит здесь.

3

или вы можете использовать AtomicInteger в качестве изменяемого целого числа.

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

Вместо использования new Long(size), вы должны использовать Long.valueOf(size). который вернет ту же длинную ссылку, которая внутренне кэширована, и также должна повысить производительность (не то, что она будет видна, если вы не будете делать миллионы этих операций new Long()).

пс. работает только для java 1.5 или выше

+0

AFAICT в 1,6 Long.valueOf только кэширует 256 лонги, расположенных вдоль нуля , Все, что выше, чем 128, не будет кэшироваться, аналогично значениям ниже -127. –

+0

для 1.6 (не 1.5 или ниже afaik) вы можете изменить это поведение, установив -XX: AutoBoxCacheMax = 1000 (см. Http://www.javaspecialists.eu/archive/Issue191.html) - tho, если ваше приложение замедляется такие операции уже есть, то я подозреваю, что существует некоторая алгоритмическая проблема ... – Chii

1

Расширение того, что написал cletus.

Его решение в порядке, за исключением того, что оно хранит только каждый размер файла, с которым вы сталкиваетесь, и количество файлов с таким размером. Если вы когда-нибудь захотите узнать, какие файлы, которые являются этой структурой данных, будут бесполезны для вас, поэтому я не думаю, что решение cletus достаточно полно. Вместо этого я бы

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

, то вы можете получить количество файлов с c.size(), и вы можете перебрать все файлы с этим числом легко, без необходимости запускать эту процедуру еще раз.

+1

Вы забыли поставить на карту аррайалиста. –

+0

спасибо! ха-ха, я, как правило, забываю об этом, и они возвращаются, чтобы укусить меня в задницу. – ldog

+0

полезное решение, хотя решение cletus ближе к тому, что мне нужно. – zeroin23

1

Я думаю, что есть еще кое-что, и нам понадобится больше деталей от вас. Я предполагаю, что вы знаете, что определенно более одного файла определенного размера, иначе я бы сначала посмотрел, чтобы это произошло. Насколько вам известно, у вас просто много файлов с уникальными размерами файлов.

Вы упомянули:

... из-за того, что каждый Long OBJ является уникальным.

Я не думаю, что это проблема. Хотя это может быть правдой в зависимости от того, как вы создаете Longs, это не должно мешать HashMaps вести себя так, как вы хотите. Пока два ключевых объекта возвращают одно и то же значение hashCode(), а метод equals() говорит, что они равны, ваш HashMap не будет создавать для него другую запись. Фактически, вам не удастся увидеть «список (filesize, 1)» с теми же значениями размера файла (если вы не написали свой собственный Long и не смогли правильно реализовать hashCode()/equals()).

Сказанное, код Cletus должен работать, если вы используете Java 5 или более поздней версии, если вы используете Java 1.4 или ниже, вам нужно либо самостоятельно сделать свой бокс/распаковку, либо посмотреть на Apache Commons Collections ,Вот версия до Java 5 примера Клетуса:

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

это произошло на машине jdk1.4.2 ... – zeroin23

 Смежные вопросы

  • Нет связанных вопросов^_^