usar titledborder setborder definicion codigo java collections clojure functional-programming

titledborder - ¿Qué es un buen marco de colecciones persistentes para usar en Java?



titledborder java (13)

Por colecciones persistentes me refiero a colecciones como las de clojure.

Por ejemplo, tengo una lista con los elementos (a, b, c). Con una lista normal, si agrego d, mi lista original tendrá (a, b, c, d) como sus elementos. Con una lista persistente, cuando llamo a list.add (d), recupero una nueva lista, sosteniendo (a, b, c, d). Sin embargo, la implementación intenta compartir elementos entre la lista siempre que sea posible, por lo que es mucho más eficiente en memoria que simplemente devolver una copia de la lista original. También tiene la ventaja de ser inmutable (si tengo una referencia a la lista original, siempre devolverá los 3 elementos originales).

Todo esto se explica mucho mejor en otra parte (por ejemplo, http://en.wikipedia.org/wiki/Persistent_data_structure ).

De todos modos, mi pregunta es ... ¿cuál es la mejor biblioteca para proporcionar esta funcionalidad para usar en java? ¿Puedo usar las colecciones de clojure de alguna manera (otras que utilizando directamente clojure)?



En la misma línea que Cornelius Mund, Pure4J transfiere las colecciones de Clojure a Java y agrega soporte para genéricos.

Sin embargo, Pure4J tiene como objetivo introducir semántica de programación pura en la JVM a través de la verificación del código de tiempo de compilación, por lo que va más allá para introducir restricciones de inmutabilidad en sus clases, de modo que los elementos de la colección no puedan mutarse mientras exista la colección.

Esto puede o no ser lo que quiere lograr: si está después de usar las colecciones de Clojure en la JVM, optaría por el enfoque de Cornelius; de lo contrario, si está interesado en seguir un enfoque de programación pura en Java, puede dar Pure4J un intento.

Divulgación: Soy el desarrollador de este


Estaba buscando un marco de colección persistente "amigable" y delgado, y tomé TotallyLazy y pcollections mencionadas en este hilo para una prueba de manejo, porque me sonaban muy prometedoras.

Ambos proporcionan interfaces razonables y simples para manipular listas persistentes:

// 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");

Tanto PersistentList como PVector extienden java.util.List , por lo que ambas bibliotecas deberían integrarse bien en un entorno existente.

Sin embargo, resulta que TotallyLazy se encuentra con problemas de rendimiento cuando se trata de listas más grandes (como ya se mencionó en un comentario de arriba por @levantpied). En mi MacBook Pro (finales de 2013), insertar 100.000 elementos y devolver la lista inmutable tomó TotallyLazy ~ 2000ms, mientras que PCollections terminó dentro de ~ 120ms.

Mis (simples) casos de prueba están disponibles en Bitbucket , si alguien quiere echar un vistazo más a fondo.



La respuesta más votada sugiere utilizar directamente las colecciones clojure, lo que creo que es una muy buena idea. Desafortunadamente, el hecho de que clojure es un lenguaje de tipo dinámico y Java no hace que las bibliotecas de clojure sean muy incómodas de usar en Java.

Debido a esto y la falta de envoltorios ligeros y fáciles de usar para los tipos de colecciones de clojure, he escrito mi propia biblioteca de envoltorios de Java utilizando genéricos para los tipos de colección de clojure con un enfoque en la facilidad de uso y la claridad cuando se trata de a las interfaces.

https://github.com/cornim/ClojureCollections

Tal vez esto sea de utilidad para alguien.

PD: Por el momento solo se han implementado PersistentVector, PersistentMap y PersistentList.


Me sorprende que nadie mencione vavr. Lo uso desde hace mucho tiempo.

http://www.vavr.io

Descripción de su sitio:

Vavr Core es una biblioteca funcional para Java. Ayuda a reducir la cantidad de código y aumentar la robustez. Un primer paso hacia la programación funcional es comenzar a pensar en valores inmutables. Vavr proporciona colecciones inmutables y las funciones y estructuras de control necesarias para operar con estos valores. Los resultados son hermosos y solo funcionan.


Puede querer revisar clj-ds . No lo he usado, pero parece prometedor. Basado en el archivo Léame de proyectos, extrajo las estructuras de datos de Clojure 1.2.0.


Solo usa los de Clojure directamente. Si bien es posible que no desee utilizar el lenguaje en sí, puede usar las colecciones persistentes directamente, ya que todas son solo clases de 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");

(descargo de responsabilidad: en realidad no he compilado ese código :)

La desventaja es que las colecciones no están escritas, es decir, no hay genéricos con ellas.


functionaljava.org implementa una Lista persistente, Lista lenta, Conjunto, Mapa y Árbol. Puede que haya otros, pero solo me baso en la información de la página principal del sitio.

También me interesa saber cuál es la mejor biblioteca de estructura de datos persistentes para Java. Mi atención se dirigió a Java funcional porque se menciona en el libro Programación funcional para desarrolladores de Java .


Paguro proporciona versiones de tipo seguro de las colecciones de Clojure reales para su uso en Java 8+. Incluye: Lista (Vector), HashMap, TreeMap, HashSet y TreeSet. Se comportan exactamente de la manera que especifica en su pregunta y se han ajustado cuidadosamente a las interfaces existentes de las colecciones java.util para lograr la máxima compatibilidad de Java con seguridad de tipos. También son un poco más rápidos que PCollections .

Codificando tu ejemplo en Paguro se ve así:

// 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

Tu dijiste,

La implementación intenta compartir elementos entre la lista siempre que sea posible, por lo que es mucho más eficiente en memoria y rápida que simplemente devolver una copia de la lista original. También tiene la ventaja de ser inmutable (si tengo una referencia a la lista original, siempre devolverá los 3 elementos originales).

Sí, así es exactamente como se comporta. Daniel Spiewak explica la velocidad y la eficiencia de estas colecciones mucho mejor que yo.


https://github.com/andrewoma/dexx es un puerto de las colecciones persistentes de Scala a Java. Incluye:

  • Set, SortedSet, Map, SortedMap y Vector
  • Adaptadores para ver las colecciones persistentes como equivalentes de java.util.
  • Ayudantes para facilitar la construcción.


totallylazy es una muy buena biblioteca de FP que tiene implementaciones de:

  • PersistentList<T> : las implementaciones concretas son LinkedList<T> y TreeList<T> (para acceso aleatorio)
  • PersistentMap<K, V> : las implementaciones concretas son HashTreeMap<K, V> y ListMap<K, V>
  • PersistentSortedMap<K, V>
  • PersistentSet<T> : la implementación concreta es TreeSet<T>

Ejemplo de uso:

import static com.googlecode.totallylazy.collections.PersistentList.constructors.*; import com.googlecode.totallylazy.collections.PersistentList; import com.googlecode.totallylazy.numbers.Numbers; ... PersistentList<Integer> list = list(1, 2, 3); // Create a new list with 0 prepended list = list.cons(0); // Prints 0::1::2::3 System.out.println(list); // Do some actions on this list (e.g. remove all even numbers) list = list.filter(Numbers.odd); // Prints 1::3 System.out.println(list);

Totalmente es mantenido constantemente. La principal desventaja es la ausencia total de Javadoc.