Allgemeines zum Projekt neco4j

neco4j (“new collections 4 Java”) ist ein Projekt, um immutable Colections und Datenstrukturen für Java 8 bereitzustellen.

Wir dachten dabei an immutable Gegenstücke zu den Standard-Collections (List, Set, Map), Tuple und Either, eventuell auch Gegenstücke zu Guava-Collections. Auch ergänzende Klassen (Zipper, Pattern-Matching) können hinzukommen.

Uns ist natürlich bekannt, dass es andere Bibliotheken in dieser Richtung gibt (functionaljava, pcollections, totally lazy…). neco4j soll sich von diesen wie folgt unterscheiden:
[ul]
[li] Größe: Eine kleine Bibliothek ohne weitere Abhängigkeiten
[/li][li] Interoperabilität: Keine “Ausgrenzung” mutabler Collections, sondern einfache Umwandlungsmöglichkeiten. Nutzung von Java-Standard-Klassen, wo es möglich ist. Am Java Standard angelehnte API.
[/li][li] Aktualität: Ausnutzung der Java 8 Features wie Lambdas, Default-Methoden u.s.w.
[/li][li] Kohärenz: Enger Bezug der Klassen aufeinander
[/li][li] Pragmatismus: Gute Performance, Verständlichkeit, keine theoretischen Spielereien.
[/li][/ul]

Zur Zeit arbeiten Marco13, cmrudolph und ich an neco4j. Wir haben beschlossen, den Code privat zu halten (BitBucket) bis wir etwas Vorzeigbares haben, was uns erst mal auf maximal 5 Committer beschränkt (sonst wird BitBucket kostenpflichtig).

*** Edit ***

Ach ja, noch eine Bemerkung zu meiner Arbeitsweise: Es mag momentan der Eindruck entstehen, dass ich bei vielen Sachen ungefragt voranpresche.

Mir ist Konsens und Diskussion in diesem Projekt sehr wichtig, und ich habe bestimmt nicht vor, hier eine Einmannshow hinzulegen. Aber ich habe auch die Erfahrung gemacht, dass nicht viel passiert, wenn man nicht einfach mal “macht”. Deshalb: Nichts ist in Stein gemeißelt, alles neue ist wirklich nur erst einmal ein Vorschlag. Wenn etwas nicht passt oder unklar ist, einfach “Stop” rufen.

Hab’ das mal Sticky gemacht. Früher oder später wäre es wohl auch nicht verkehrt, das auf Englisch zusammenzuschreiben, aber im Moment ist es ja noch recht früh. (Übrigens stimme ich dem letzten Absatz zu, eine konkrete Diskussionsgrundlage ist bei sowas wohl schon hilfreich)

@Landei : Möchtest du ein eigenes Projekt-Forum haben? So wie Apo, Beni, Marco13 und Schlingel?

Danke für das Angebot, aber ehrlich gesagt denke ich, dass sich das bei mir (noch?) nicht lohnt.

(Wäre das etwas anderes, als (hier) Mod-Rechte zu haben? Unabhängig davon wäre jemand, der sich den Project-Lead-Hut aufsetzt, nicht schlecht :D)

Du meinst sowas?

Jetzt weiß ich auch endlich, wieso man den so nennt: Weil die Verantwortung der Projektführung so schwer wiegt.
Und wenn bei dir schon so ein Hut rum liegt, dann kannst du den gerne aufsetzen. So wie ich das aus diesem Thread entnehme, bist du von uns dreien sowieso der einzige, der sich wirklich gut mit der Materie auskennt.

Du Lex guck mal wo du hier bist :wink:

Oh, ich sehe jetzt erst, dass ich hier Mod-Rechte habe…

*** Edit ***

Dann setzte ich mir die Blei-Melone auf. Wenn sie nicht passt, kann ich sie ja zurechthämmern…

Hat das jemand heimlich still und leise gemacht…? Wieso krieg ich hier nix mehr mit?
…und wieso sitzt der Lehrling hier faul rum? :wink: :smiley:

Hi Leute,

bin neu hier und arbeite gerade an einem ähnlichen Projekt mit (LazySeq). Es befindet sich allerdings auch noch im beta-Stadium.

Mich würde interessieren, welche Ziele Ihr mit Eurem Projekt verfolgt. Da ich in den letzten 4 Jahren viel mit Scala gemacht habe, vermisse ich in Java vor allem eine gut lesbare, kompakte Notation für Sequenzen von funktionalen Operatoren auf Collections, wie z.B.:

trainingGroups.filter(tg -> tg.year > 2000).flatMap(tg -> tg.sportsmen).groupBy(s -> s.yearOfBrith).mapValues(group -> group.size()).toMap();

Die Steam-Klasse von Java ist da keine sonderlich große Hilfe. Viele High-Level-Operatoren fehlen oder sind nicht wirklich schön in ihrer Anwendung.

Tomasz Nurkiewicz hat mit LazySeq da bereits eine halbe Alternative zur Stream-Klasse entwickelt. Was haltet Ihr eigentlich von dem Projekt und verfolgt Ihr mit Eurem Projekt ein ähnliches Ziel wie ich?

Das “LazySeq” sieht interessant aus (ich meine, bei ersten Websuchen schonmal drüber gestolpert zu sein, aber vielleicht verwechsle ich das auch gerade mit https://code.google.com/p/totallylazy/ ).

Das Besipiel, das du gepostet hast, hat mich aber etwas irritiert. Genau das geht doch jetzt genau so mit den Streams?! (oder ich habe nicht verstanden, was du mit “high-level-Operatoren” meintest…)

Die Abgrenzung von neco4j gegenüber anderen, ähnlichen Bibliotheken ist ein … interessanter, aber auch etwas “heikler” Punkt. (Ähnlich wie die Frage nach der Abgrenzung der anderen Bibliotheken untereinander :D). Ich will da nicht für andere sprechen, und halte mich mal etwas zurück.

Meine ganz persönliche Abgrenzung:

Mir schwebte eine kleine, kompakte und pragmatische (insbesondere bezüglich der Zusammenarbeit mit den java.util - Collections) Bibliothek vor. Was mir bei vielen ähnlichen Projekten fehlte, waren Tupel und Either, und deren Integration mit den “richtigen” Collection-Klassen. Mir fällt nur FunctionalJava ein, wo das mit dabei ist, aber dort kommt sehr viel anderer Ballast mit, außerdem ist die Bibliothek erst am Anfang der Java 8-Umstellung (und das sieht nicht immer besonders bequem aus).

Bezüglich der Laziness herrscht bei uns eindeutig noch Klärungsbedarf. Ich will auf jeden Fall auch eine strikte Implementierung, aber um irgend eine Form der Laziness werden wir nicht herumkommen. Eine klare Strukturierung ist da schwieriger, als man denkt.

Ach ja, und wenn meine Idee mit dem (eingeschränkten) Pattern-Matching klappt, wäre das auch ein Alleinstellungsmerkmal.

‘‘Genau so’’ wie in meinem Beispiel geht es mit der Java-Stream-Klasse leider nicht. So fehlen bei der Stream-Klasse beispielsweise die Methoden groupBy, mapValues, toMap.

Um groupBy(s -> s.yearOfBrith) mittels Stream auszudrücken, müsste man beispielsweise folgendes schreiben:
collect(Collectors.groupingBy(s -> s.yearOfBrith)).entrySet().stream()

Und für toMap() folgendes:
collect(Collectors.toMap(x -> x.key, x -> x.value))

Für sortedBy(x -> x.attribute) folgendes:
sort(Comparator.comparing(x -> x.attribute)

Letztendlich bekommt man mit der ‘‘Stream’’-Klasse schon fast alles hin, doch die Syntax ist mir einfach zu weitschweifig und für meine Begriffe auch zu übermodularisiert. Dass beispielsweise die sort-Funktion nur einen Comparator verarbeiten kann statt auch Lambda-Ausdrücke zu akzeptieren, lässt mich stark daran zweifeln, dass die Java-Entwickler die Bedeutung der Lambda-Ausdrücke verstanden haben. Die bisher umständliche Definition von Comparatoren wird in Zukunft meines Erachtens komplett durch Lambda-Ausdrücke ersetzt werden. Zum einen sind die meisten Sortierungsoperationen eh nur Sortierungen auf einem Attribut (x -> x.attribute). Und zum anderen lassen sich die verbleibenden 5-10% der Fälle einfacher durch eine Funktion à la (a, b) -> a.compareTo(b) statt durch einen Comparator beschreiben.

*** Edit ***
@Landei
Klingt gut. Das sind auch meine Ziele. Either (oder Optional, wie es unter Java8 heißt) und Tupel halte ich dabei auch für unabkömmlich. Schade nur, dass es unter Java keine Tupel-Notation wie unter Scala gibt. Nachdem in Java8 die Notation _(a,b) nicht mehr möglich ist, bin ich mit der Alternative t(a,b) nicht so recht glücklich. Kennt jemand eine schickere Form, die dennoch leicht zu tippen ist?

Was die Zusammenarbeit mit den Java-Collections-Klassen angeht, verfolgt LazySeq wohl das gleiche Ziel. Ein- und Ausgaben sind eigentlich immer die Java-Collections oder Arrays. Und die LazySeq selbst implementiert auch das AbstractList-Iterface, sodass man z.b. in for-Schleifen auch direkt damit arbeiten kann. Und mit der LazyTupleSeq (nur in meinem Repo) gibt es auch eine spezielle Unterstützung für Sequenzen von Tuples, die weitere nette High-Level-Operatoren wie toMap, mapValues, usw. bereitstellen.

Wir hatten auch eine Diskussion, ob wir das List- oder Collection-Interface implementieren wollen, haben uns aber wegen der UnsupportedOperationExceptions dagegen entschieden.

Was den Unterstrich angeht, könnte man vielleicht noch $ verwenden. In einer Bibliothek habe ich zu anderen Zwecken das µ missbraucht.

Hm, $(a,b) lässt sich auch gut schreiben und hebt sich in der Tat besser als t(a,b) vom restlichen Java-Code ab. Danke für den Tipp. Werde es verwenden!

Nur so am Rande, falls jemand wie ich Probleme mit dem aktuellen Java 8 Build 25 hat: Als Workaround hat bei mir die Early Access von Build 40 funktioniert, siehe https://jdk8.java.net/download.html

Hiermit erkläre ich neco4j offiziell für tot. Das javaslang-Projekt kann alles, was ich mir von neco4j erhofft hatte (und mehr).

Schade.
Glaub’ ich.
Ein kurzer Blick über die API docs sieht einerseits recht sauber und straightforward aus (es GIBT eine “gute”, vollständige, verlinkte API-Doc - das ist nicht selbstverständlich…). Bei den Namen von λ (Javaslang 2.0.1 API) oder auch Set (Javaslang 2.0.1 API) kann man zwar nur mit den Augen rollen, aber bestimmte Konzepte scheinen (soweit ich das beurteilen kann (nicht sehr weit, aber)) recht vernünftig und “bequem verwendbar” umgesetzt zu sein. Ggf. mal schauen, wie es sich anfühlt, das wirklich zu verwenden.