Hello! I can imagine that we have somewhere in the library a FunctionHelper interface like this:
interface FunctionHelper<R, T> { default Predicate<? super R> is(T value) { return r -> Objects.equals(map().apply(r), value); } default Predicate<? super R> not(T value) { return r -> !Objects.equals(map().apply(r), value); } default Consumer<? super R> consume(Consumer<? super T> consumer) { return r -> consumer.accept(map().apply(r)); } // maybe more function adapters Function<? super R, ? extends T> map(); static <R, T> FunctionHelper<R, T> forAccessor(Function<? super R, ? extends T> accessor) { return () -> accessor; } } Then we generate static fields that correspond to every record component: record Point(int x, int y) { public static final FunctionHelper<Point, Integer> X = FunctionHelper.forAccessor(Point::x); public static final FunctionHelper<Point, Integer> Y = FunctionHelper.forAccessor(Point::y); } Then we can use them: var points = List.of(new Point(1, 2), new Point(3, 4), new Point(5, 6)); points.forEach(Point.X.consume(System.out::println)); points.stream().filter(Point.Y.is(4)).forEach(System.out::println); points.stream().filter(Point.Y.not(4)).forEach(System.out::println); Of course, nobody will do this but it looks nice to me. With best regards, Tagir Valeev On Tue, Mar 17, 2020 at 4:58 PM Remi Forax <fo...@univ-mlv.fr> wrote: > Hi Daniel, > Pooling of Java objects in memory usually do more harm than good, because > you artificially change the liveness of the pooled objects which doesn't > work well with modern GC algorithms. > Obviously, if objects are stored in a database, it can still be a win but > usually the pool is more or less coupled with the ORM and use off-heap > memory. > > EnumSet/EnumMap are specialized because Enum.ordinal() is a perfect > hashcode function, so you can implement fast and compact set and map. It's > not clear to me why there is a need for a specialized version of set/map > for record given has you said a record is a class. Do we miss something ? > > About filtering fields value on stream, adding a method isEqual that takes > a mapping function and a value should be enough, > Predicate<Point> filter = Predicate.isEqual(Company::name, "Apple"); > I remember the lambda EG discuss that method (and its primitive > variations), i don't remember why it's was not added. > > About introducing a typesafe representation of fields, we currently > provide a non-typesafe representation, j.l.r.RecordComponent. > There is no typesafe representation because what :: means on a field is > still an open question. > And if we go that way, a static final field is not the best representation > in term of classfile because it is initialized too early. A ldc > constantdynamic + a static method or something along that line is a better > idea. > > regards, > Rémi > > ------------------------------ > > *De: *"Brian Goetz" <brian.go...@oracle.com> > *À: *"amber-spec-experts" <amber-spec-experts@openjdk.java.net> > *Envoyé: *Lundi 16 Mars 2020 21:24:04 > *Objet: *Fwd: [Records] Transparency and effects on collections > > Received on the -comments list. > > > -------- Forwarded Message -------- > Subject: [Records] Transparency and effects on collections > Date: Wed, 11 Mar 2020 07:45:32 -0700 (PDT) > From: Daniel Latrémolière <daniel.latremoli...@gmail.com> > <daniel.latremoli...@gmail.com> > To: amber-spec-comme...@openjdk.java.net > > > I understand that records are transparent and have correct > equals/hashcode, then are useful as keys in collections. When trying to > find classes to evolve to records, I found classes having more or less the > same use-cases in memory than a multi-column primary key would have in SQL. > ------------------------------------------------------------------------ > Records are a sugar above classes, like enum but for another use case, is > it planned to have more evolved collections (like enum has with > EnumSet/EnumMap)? Given records are explicitly transparent, API for pooling > records would need to use this explicit transparency to allow partial > queries and not only the Set/Map exact operations. > > If this is the case, it would probably need some specialised subtype of > Set, like a new RecordSet (similar to a simple table without join, contrary > to SQL). Current Java's Stream API would probably be perfect with some > small enhancements, JPA-like (on a sub-type RecordStream<R>) allowing to > refer directly to the field to be filtered. > > In this case, the compiler would need to generate for each record one > static field per instance field of the record to allow typed queries, like > in the following example. > > |record R(|||String foo, ...)| {|| > || ...|| > ||}|| > | > desugarized more completely in: > > |class R {|| > || public static final RecordField<R, String> FOO;|| > || private String foo;|| > || ...|| > ||}|| > | > It would allow some typed code for partial querying, like: > > |RecordSet<R> keyPool;|| > ||Predicate<String> fooFilter;|| > ||keyPool.stream().filter(R.FOO, fooFilter).forEach(...);|| > | > > Thanks for your attention, > Daniel. > ------------------------------------------------------------------------ > NB: in desugarization, I used standard static fields, like JPA, and not an > enum containing all meta-fields (which would probably be more correct and > efficient). This is due to the lack of JEP 301 (needed for typed constants > in enum). If allowed, the desugarized record will become something like: > > |class R {|| > || public static enum META<X> implements RecordField<R, X> {|| > || FOO<String>(String.class);|| > || }|| > || private String foo;|| > || ...|| > ||}|| > | > In query, it would be used as R.META.FOO for filtering on field "foo" of > the record: > > |keyPool.stream().filter(R.META.FOO, fooFilter).forEach(...)| > ------------------------------------------------------------------------ > PS: I am not interested in interning records but using them in pools > defined by programmer. Pooling would improve memory and performance to > deduplicate records, because equals would more frequently succeed at > identity test without continuing to real equality test (field by field). > Having specialized implementations of collections, using fields of records > following the order given by user, would probably be useful for performance > against simple Set/Map: structures like a hierarchical Map of Map of ..., > field by field, can be more efficient if partial queries are frequently > used or if the pool is big. > >