2009-03-10 2 views
131

Что представляет собой наиболее эффективная библиотека Java Collections?Что представляет собой наиболее эффективная библиотека сборников Java?

Несколько лет назад я сделал много Java и имел впечатление, что trove - лучшая (наиболее эффективная) реализация Java Collections. Но когда я прочитал ответы на вопрос «Most useful free Java libraries?« Я заметил, что trove вряд ли упомянут. Итак, какая библиотека библиотек Java теперь лучше?

UPDATE: Чтобы уточнить, я в основном хочу знать, какую библиотеку использовать, когда я должен хранить миллионы записей в хеш-таблице и т. Д. (Требуется небольшая продолжительность выполнения и объем памяти).

+0

Каковы ключи и значения в этой таблице? Если они не примитивы, что не так с обычным HashMap и т. Д.? –

+0

Для очень большой карты вам может понадобиться реализация зондирования или даже встроенная таблица базы данных. –

+1

Интересно, я не вижу упоминания о Кольте, который впоследствии был включен в Махут. – smartnut007

ответ

70

От инспекции, похоже, что Trove - это всего лишь библиотека коллекций для примитивных типов - это не похоже на то, что она добавляет много функциональности по сравнению с обычными коллекциями в JDK.

Лично (и я предвзято) Я люблю Guava (включая бывший проект Google Java Collections). Это делает различные задачи (включая коллекции) намного проще, что, по крайней мере, разумно эффективно. Учитывая, что операции по сбору данных редко составляют узкое место в моем коде (по моему опыту), это «лучше», чем API коллекций, который может быть более эффективным, но не делает мой код доступным для чтения.

Учитывая, что перекрытие между Trove и Guava в значительной степени ноль, возможно, вы могли бы прояснить, что вы действительно ищете из библиотеки коллекций.

+0

следует отметить, что для большинства задач коллекции google слишком сложны, а коллекции java более чем достаточны. –

+3

@ Андреас: Не могу сказать, что согласен. Не то, чтобы это сценарий «один или другой» - я использую регулярные коллекции (с помощниками, такими как класс «Списки»), а затем использовать Iterables и т. Д., Когда мне это нужно. Используйте сложность только тогда, когда она вам помогает. –

+9

после прочтения собственного комментария через несколько месяцев после широкого использования G-C - я не согласен с моим прошлым мнением и полностью согласен с вашим. используйте вспомогательные методы/классы, они делают большую часть кода более читабельным и безопасным. –

7

java.util

Извините за очевидный ответ, но для большинства применений, по умолчанию Java Collections более чем достаточно.

+3

Для базового использования да. Но я думаю, что структура пропускает некоторые базовые и расширенные функции (например, неизменные коллекции, фильтры, мультиплексы и т. Д.), И вот где (например) Google Collections приходит в – Jorn

+1

. Я думаю, что этот ответ не подходит. JCF, вероятно, был потрясающим в 2002 году люди не использовали использование Java для многих, но, к сожалению, он плохо выдерживает, особенно по сравнению с поддержкой коллекций с других языков JVM. –

+2

-1 Вопрос «наиболее эффективен для хранения int», и любой упомянутый пример лучше, чем java.util – kommradHomer

2

ConcurrentHashMap, а также пакет java.util.concurrent, если вы планируете использовать HashMap в нескольких потоках. ограниченный объем памяти, поскольку это часть стандартной java.

3

В зависимости от того, как мы определяем «эффективный».

Каждая структура данных имеет собственное поведение Big-Oh для чтения, записи, итерации, объема памяти и т. Д. Связанный список в одной библиотеке, вероятно, будет таким же, как и любой другой. И хэш-карта будет быстрее для чтения O (1), чем связанный список O (n).

Но когда я прочитал ответы на вопрос «Самые полезные бесплатные библиотеки Java?» Я заметил, что это трудно сказать.

Это не похоже на «наиболее эффективный». Это звучит как «самый популярный» для меня.

Только некоторые отзывы - я никогда не слышал об этом, и я не знаю никого, кто его использовал. Коллекции, встроенные в JDK, Google или Apache Commons, хорошо известны мне.

3

Trove предлагает несколько преимуществ.

  • меньший объем памяти, он не используется. Карта.Объекты ввода
  • вы можете использовать стратегии хэша вместо ключей для карт, это экономит память и означает, что вам не нужно определять новый ключ каждый раз, когда вы хотите кэшировать объект по новому набору его атрибутов.
  • он имеет примитивные типы коллекций
  • думаю, что есть некоторая форма внутреннего итератора

это сказало, много было сделано для улучшения коллекции JDK, так как сокровищница была написана.

Это стратегии хэширования, которые делают его привлекательным для меня, хотя ... Google заработает и прочитает их обзор.

19

Как заметили другие комментаторы, определение «эффективный» отличает широкую сеть. Однако никто еще не упомянул Javolution library.

Некоторые из основных моментов:

  • классы Javolution быстро, очень быстро (например, вставка текста/удаление в O [Log (N)] вместо O [N] для стандартного StringBuffer/StringBuilder).
  • Все классы Javolution являются жесткими в режиме реального времени и имеют очень детерминированное поведение (в микросекундах). Кроме того (в отличие от стандартной библиотеки) Javolution является безопасным RTSJ (при использовании с расширением Java Real-Time не происходит утечки памяти или утечки памяти).
  • Классы сбора данных реального времени Javolution (карта, список, таблица и множество) могут использоваться вместо большинства стандартных классов коллекции и обеспечивать дополнительную функциональность.
  • Коллекции Javolution предоставляют гарантии параллелизма для упрощения реализации параллельных алгоритмов.

В дистрибутив Javolution входит эталонный набор, чтобы вы могли видеть, как они складываются с другими библиотеками/встроенными коллекциями.

15

Некоторые ЛИЭС коллекции рассмотреть следующие вопросы:

Я бы прежде всего добрался до библиотеки коллекций JDK. Он охватывает наиболее распространенные вещи, которые вам нужно сделать и, очевидно, уже доступен для вас.

Коллекции Google - это, вероятно, лучшая высококачественная библиотека за пределами JDK. Он сильно используется и хорошо поддерживается.

Коллекции Apache Commons старше и немного страдают от проблемы «слишком много поваров», но также имеет массу полезных вещей.

Trove имеет очень специализированные коллекции для таких случаев, как примитивные ключи/значения.В наши дни мы обнаруживаем, что на современных JDK и с коллекциями Java 5+ и одновременными вариантами использования коллекции JDK выходят за рамки специализированных коллекций Trove.

Если у вас действительно высокие возможности использования параллелизма, вы должны обязательно проверить такие вещи, как NonBlockingHashMap в высокоуровневой библиотеке lib, которая является блокировкой и может топать на ConcurrentHashMap, если у вас есть правильный вариант использования ,

+7

«В наши дни мы обнаруживаем, что на современных JDK и с коллекциями Java 5+ и одновременными вариантами использования JDK collecti ons out-perform даже специализированные коллекции Trove. » Вводящий в заблуждение - я никогда не видел микро-бенчмарк, где хранение/извлечение примитивных типов в специализированном классе примитивных коллекций, таких как Trove, не превосходила классы коллекции JDK как в использовании памяти и процессорное время. Если вы используете объекты (а не примитивные типы), то я бы согласился с Алексом, беспокоясь о том, что сборник не так велик. –

+2

Это заявление было основано на тяжелом использовании в реальном мире (которое я возьму на себя в течение нескольких месяцев) в различных коллекциях, где нам понадобилась коллекция Trove, но теперь они смогли ее вытащить. Поздние обновления JDK 6 (около конца 2009 года) фактически предоставили специальный код для общих ключей карты, таких как Integer, которые существенно улучшили некоторые из наиболее распространенных применений. –

+1

Alex, я не сомневаюсь в ваших конкретных случаях использования, что вытащить примитивные коллекции и собираться с коллекциями JDK было достаточно быстро, но размахивая рукой через пейзаж, который является коллекциями, и говоря: «Все, что вы проходите, достаточно быстро !» неточно. Если я работаю над движком 2D-игр, накладные расходы на бокс/распаковку моих примитивных типов постоянно значительно дороже. Если я работаю над REST API, то нет, он, вероятно, не делает измеримых различий вообще по отношению к гораздо более дорогим операциям, таким как HTTP I/O. Я просто чувствовал себя вынужденным количественно оценить ваше сообщение. –

2

Если вы хотите хранить миллионы записей в хеш-таблице, скорее всего, вы столкнетесь с проблемами памяти. Это случилось со мной, когда я попытался создать карту с 2,3 миллионами объектов String, например. Я пошел с BerkeleyDB, который очень зрелый и хорошо работает. У них есть API Java, который обертывает API Collections, поэтому вы можете легко создавать произвольно большие карты с очень небольшим объемом памяти. Доступ будет медленнее, хотя (поскольку он хранится на диске).

Последующий вопрос: есть ли достойная (и эффективная), ухоженная библиотека для неизменных коллекций? Clojure имеет отличную поддержку для этого, и было бы неплохо иметь что-то подобное для Java.

+1

Коллекции Google добавляют неизменные коллекции. –

98

Вопрос (сейчас) о хранении большого количества данных, которые могут быть представлены с использованием примитивных типов, таких как int, на карте. Некоторые из ответов здесь, по моему мнению, очень вводят в заблуждение. Давайте посмотрим, почему.

Я изменил бенчмарк от trove, чтобы измерить как время работы, так и потребление памяти. Я также добавил PCJ к этому эталону, который представляет собой еще одну библиотеку коллекций для примитивных типов (я использую эту экстенсивно). «Официальный» контрольный ориентир не сравнивает IntIntMaps с Java Collection Map<Integer, Integer>, вероятно, сохраняя Integers, а хранение ints не совпадает с технической точки зрения. Но пользователь может не заботиться об этой технической детали, он хочет эффективно хранить данные, представленные с помощью ints.

Первая соответствующая часть кода:

new Operation() { 

    private long usedMem() { 
     System.gc(); 
     return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
    } 

    // trove 
    public void ours() { 
     long mem = usedMem(); 
     TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE); 
     for (int i = dataset.size(); i-- > 0;) { 
      ours.put(i, i); 
     } 
     mem = usedMem() - mem; 
     System.err.println("trove " + mem + " bytes"); 
     ours.clear(); 
    } 

    public void pcj() { 
     long mem = usedMem(); 
     IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE); 
     for (int i = dataset.size(); i-- > 0;) { 
      map.put(i, i); 
     } 
     mem = usedMem() - mem; 
     System.err.println("pcj " + mem + " bytes"); 
     map.clear(); 
    } 

    // java collections 
    public void theirs() { 
     long mem = usedMem(); 
     Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE); 
     for (int i = dataset.size(); i-- > 0;) { 
      map.put(i, i); 
     } 
     mem = usedMem() - mem; 
     System.err.println("java " + mem + " bytes"); 
     map.clear(); 
    } 

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

Результаты среды выполнения (без gc() звонков, конечно) на WinXP, jdk1.6.0_10:

 
         100000 put operations  100000 contains operations 
java collections    1938 ms      203 ms 
trove       234 ms      125 ms 
pcj       516 ms       94 ms 

Хотя это может показаться уже резким, это не причина, чтобы использовать такую ​​структуру.

Причина - производительность памяти. Результаты для карты, содержащей 100000 int записей:

 
java collections  oscillates between 6644536 and 7168840 bytes 
trove          1853296 bytes 
pcj          1866112 bytes 

Java Collections необходим более чем три раза памяти по сравнению с примитивными рамками сбора. То есть вы можете хранить в три раза больше данных в памяти, не прибегая к дискам IO, что снижает производительность во время выполнения по величинам. И это имеет значение. Прочтите highscalability, чтобы узнать, почему.

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

So: Нет, java.util не является ответом. И «добавление функциональности» в коллекции Java не является вопросом, когда вы спрашиваете об эффективности. Также современные коллекции JDK делают не «вытесняют даже специализированные коллекции Trove».

Отказ от ответственности: Тест здесь далеко не полный, и он не идеален. Он предназначен для того, чтобы довести дело до конца, что я испытал во многих проектах. Примитивные коллекции достаточно полезны, чтобы терпеть fishy API - , если вы работаете с большим количеством данных.

+3

На самом деле, я думаю, что ваш ответ вводит в заблуждение. Хранение ints vs Integer очень отличается и, скорее всего, является основной причиной увеличения использования памяти. Я согласен с тем, что структура исходного типа может быть полезна, но она не делает trove или pcj «лучше», чем java.util. – Jorn

+20

Вопрос в том, чтобы эффективно хранить данные int. Не о хранении целых чисел. Для этой задачи trove/pcj более эффективны, как я пытался показать. Использование целых чисел приводит к неэффективности выполнения и памяти. Поскольку java.util не позволяет использовать примитивы, это не лучший выбор для этой задачи. –

+2

(для русского сообщества) здесь идет еще один тест: http://total-holywar.blogspot.com/2011/07/java-collections-framework.html –

6

Чтобы сохранить миллионы String в карте, посмотри на http://code.google.com/p/flatmap

+3

+1 Можете ли вы представить, как он усилен? –

+1

Должны быть записи в блоге автором плоской карты где-то в Интернете. – akuhn

38

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

Вот более обоснованный анализ с точки зрения механических характеристик и библиотек. This - это нить в списке разработчиков mahout.

библиотеки охватываются

  • HPPC
  • Trove
  • FastUtil
  • Mahout (Colt)
  • Java Коллекции

Обновление июня 2015: К сожалению, исходные тесты больше не доступны и, кроме того, немного устарели. Here - довольно недавние (январь 2015 года) тесты, сделанные кем-то другим. Это не так всеобъемлюще, и у него нет интерактивных поисковых инструментов в качестве исходной ссылки.

+1

Спасибо. Это было очень полезно. Учитывая важность вопроса, трудно поверить, что ни один из других ответов (кроме the.duckman's) не отвечает на этот вопрос. – Dexter

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