Что такое хорошая постоянная коллекция коллекций для использования в Java? - PullRequest
27 голосов
/ 20 декабря 2011

Под постоянными коллекциями я подразумеваю коллекции, подобные тем, что в clojure.

Например, у меня есть список с элементами (a, b, c).С обычным списком, если я добавлю d, мой исходный список будет иметь (a, b, c, d) в качестве своих элементов.С постоянным списком, когда я вызываю list.add (d), я получаю новый список, содержащий (a, b, c, d).Тем не менее, реализация пытается разделить элементы между списками, где это возможно, так что это намного более эффективно использует память, чем просто возврат копии исходного списка.Он также имеет преимущество в том, что является неизменным (если я держу ссылку на исходный список, он всегда будет возвращать исходные 3 элемента).

Все это объясняется гораздо лучше в других местах (например, * 1006).*

В любом случае, мой вопрос ... Какая библиотека лучше всего обеспечивает эту функциональность для использования в Java? Могу ли я как-то использовать коллекции clojure (кроме как с помощью непосредственного использования clojure)?

Ответы [ 13 ]

16 голосов
/ 20 декабря 2011

Просто используйте те, которые в Clojure напрямую.Хотя очевидно, что вы, возможно, не захотите использовать сам язык, вы все равно можете использовать постоянные коллекции напрямую, поскольку все они являются просто классами Java.

import clojure.lang.PersistentHashMap;
import clojure.lang.IPersistentMap;

IPersistentMap map = PersistentHashMap.create("key1", "value1");

assert map.get("key1").equals("value1");
IPersistentMap map2 = map.assoc("key1", "value1");

assert map2 != map;
assert map2.get("key1").equals("value1");

(заявление об отказе: на самом деле я не скомпилировал этот код:)

недостатком является то, что коллекции не напечатаны, то есть с ними нет генериков.

10 голосов
/ 20 декабря 2011

Как насчет pcollections ?

Вы также можете проверить реализацию постоянных коллекций Clojure (например, PersistentHashMap ).

5 голосов
/ 23 октября 2015

Я искал тонкий, "дружественный" Java постоянный фреймворк и взял TotallyLazy и PCollections , упомянутые в этой теме, для тест-драйва, потому что они звучали для меня наиболее многообещающе.

Оба предоставляют разумные простые интерфейсы для управления постоянными списками:

// TotallyLazy
PersistentList<String> original = PersistentList.constructors.empty(String.class);
PersistentList<String> modified = original.append("Mars").append("Raider").delete("Raider");

// PCollections
PVector<String> original = TreePVector.<String>empty();
PVector<String> modified = original.plus("Mars").plus("Raider").minus("Raider");

Оба PersistentList и PVector расширяют java.util.List, поэтому обе библиотеки должны хорошо интегрироваться в существующую среду.

Оказывается, однако, что TotallyLazy сталкивается с проблемами с производительностью при работе с большими списками (как уже упоминалось в комментарии выше @levantpied). На моем MacBook Pro (конец 2013 г.) для вставки 100 000 элементов и возврата неизменяемого списка потребовалось TotallyLazy ~ 2000 мс, тогда как PCollections завершил работу в течение ~ 120 мс.

Мои (простые) тестовые случаи доступны на Bitbucket , если кто-то хочет взглянуть более тщательно.

4 голосов
/ 01 апреля 2014

https://github.com/andrewoma/dexx - это порт постоянных коллекций Scala для Java.Он включает в себя:

  • Set, SortedSet, Map, SortedMap и Vector
  • Адаптеры для просмотра постоянных коллекций в виде эквивалентов java.util
  • Помощники для простого построения
3 голосов
/ 03 октября 2015

Paguro предоставляет безопасные по типу версии актуальных коллекций Clojure для использования в Java 8+. Он включает в себя: List (Vector), HashMap, TreeMap, HashSet и TreeSet. Они ведут себя точно так, как вы указали в своем вопросе, и были тщательно подобраны к существующим java.util интерфейсам коллекций для максимальной совместимости с типом Java. Они также немного быстрее, чем PCollections .

Кодирование вашего примера в Paguro выглядит следующим образом:

// List with the elements (a,b,c)
ImList<T> list = vec(a,b,c);

// With a persistent list, when I call list.add(d),
// I get back a new list, holding (a,b,c,d)
ImList<T> newList = list.append(d);

list.size(); // still returns 3

newList.size(); // returns 4

Вы сказали,

Реализация пытается разделить элементы между списком везде, где это возможно, поэтому он намного эффективнее и быстрее просто возвращая копию оригинального списка. Он также имеет преимущество того, чтобы быть неизменным (если я держу ссылку на оригинал список, то он всегда будет возвращать исходные 3 элемента).

Да, именно так и ведет себя. Даниэль Спивак объясняет скорость и эффективность этих коллекций гораздо лучше, чем я мог.

3 голосов
/ 06 февраля 2013

Есть библиотека pcollections (Постоянные коллекции), которую вы можете использовать:

http://code.google.com/p/pcollections/

3 голосов
/ 07 августа 2012

Функциональная Java реализует постоянный список, отложенный список, набор, карту и дерево. Могут быть и другие, но я просто иду по информации на первой странице сайта.

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

3 голосов
/ 20 декабря 2011

Может захотеть проверить clj-ds . Я не использовал это, но это кажется многообещающим. Основываясь на проектах readme, он извлек структуры данных из Clojure 1.2.0.

2 голосов
/ 30 октября 2015

В том же ключе, что и Корнелиус Мунд, Pure4J переносит коллекции Clojure в Java и добавляет поддержку Generics.

Однако Pure4J нацелен на представление чистой семантики программирования в JVM посредством проверки кода времени компиляции, поэтому он идет дальше, вводя ограничения неизменяемости для ваших классов, чтобы элементы коллекции не могли быть изменены во время существования коллекции.

Это может быть или не быть тем, чего вы хотите достичь: если вы только после использования коллекций Clojure на JVM, я бы использовал подход Корнелиуса, в противном случае, если вы заинтересованы в реализации подхода чистого программирования в Java, Вы можете попробовать Pure4J.

Раскрытие информации: я разработчик этого

1 голос
/ 30 августа 2018

Я удивлен, что никто не упомянул vavr. Я давно пользуюсь им.

http://www.vavr.io

Описание с их сайта:

Ядро Vavr - это функциональная библиотека для Java. Это помогает уменьшить объем кода и повысить надежность. Первый шаг к функциональному программированию - начать думать в неизменных ценностях. Vavr предоставляет неизменные коллекции и необходимые функции и управляющие структуры для работы с этими значениями. Результаты прекрасны и просто работают.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...