JEP 186: Collection Literals
Howard Lovatt
howard.lovatt at gmail.com
Thu Feb 20 00:22:25 PST 2014
There are pros and cons to the static var args method approach.
Pros: 1. It is simple. 2. For some structures the auto created var args
array is ideal, e.g. a Collection and List.
Cons: 1. For some structures like Set, Map, and Stream you don't want the
auto created var arg array and it has to be discarded. 2. For things like
Map it is clunky because you have to create intermediate Entries.
The builder pattern offers more flexibility and you can make the object
been built its own builder and therefore eliminate any intermediate object
creation, i.e. no equivalent of the auto created var args array.
e.g.:
public interface Builder<V, C> extends Consumer<V> {
// void accept(V v); From Consumer
C build();
}
public interface BiBuilder<K, V, C> extends BiConsumer<K, V> {
// void accept(K k, V v); from BiConsumer
C build();
}
IntBulder, BiIntBuilder, etc.
public interface MyStream<V> extends Stream<V>, Builder<V,
MyStream.MyBuilder<V>> {
public interface MyBuilder<V> extends Stream.Builder<V>, Builder<V,
Stream<V>> {}
}
public interface MyCollection<V> extends Collection<V>, Builder<V,
MyCollection<V>> {
static <V> MyCollection<V> builder() { return
/*Collections.unmodifiableCollection(*/new MyArrayList<>()/*)*/; };
default void accept(final V v) { add(v); };
default MyCollection<V> build() { return this; }
}
public interface MyMap<K, V> extends Map<K, V>, BiBuilder<K, V, MyMap<K,
V>> {
static <K, V> MyMap<K, V> builder() { return
/*Collections.unmodifiableMap(*/new MyIdentityHashMap<>()/*)*/; }
default void accept(final K k, final V v) { put(k, v); }
default MyMap<K, V> build() { return this; }
}
public class MyArrayList<V> extends ArrayList<V> implements MyCollection<V>
{
public static <V> MyArrayList<V> builder() { return new MyArrayList<>(); }
@Override public MyArrayList<V> build() { return this; }
}
public class MyIdentityHashMap<K, V> extends IdentityHashMap<K, V>
implements MyMap<K, V> {
public static <K, V> MyIdentityHashMap<K, V> builder() { return new
MyIdentityHashMap<>(); }
@Override public MyIdentityHashMap<K, V> build() { return this; }
}
(In practice you would change Stream etc. rather than have MyStream etc.,
but I wanted to present tested code.)
Both the Builder and var args approaches have their merits, but I like the
efficiency and flexibility of the builder pattern.
On 20 February 2014 05:02, Stephen Colebourne <scolebourne at joda.org> wrote:
> On 21 January 2014 19:39, Brian Goetz <brian.goetz at oracle.com> wrote:
> > 3. The real pain is in Maps, not Lists, Sets, or Arrays. Library-based
> > solutions would be mostly acceptable for the latter, but we still lack a
> > reasonable way to describe pair literals, which is what's in the way of
> > a library-based solution for Map (other than a MapBuilder.) Static
> > methods in interfaces make a library-based solution more practical.
> > With value types, though, library-based solutions for Map become far
> > more practical too.
>
> Just to note on this, I previously sent a proposal to core-libs:
> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-June/010228.html
> and a proof of concept patch:
> https://gist.github.com/jodastephen/6659515
>
> The heart of the concept was static methods on interfaces:
> Collection.empty()
> Collection.of(T...)
> List.empty()
> List.of(T...)
> Set.empty()
> Set.of(T...)
> Map.empty()
> Map.of(Entry...)
> Map.Entry.of(K, V)
>
>
> Each of these methods would return immutable implementations. There is
> a case for extending the methods to Iterator and other collection
> types, however these are the most important. These follow the designs
> of Stream static methods IIRC.
>
> I think a complete solution would involve matching static methods on
> the collection classes as well, eg
> ArrayList.of(T...)
> TreeSet.of(T...)
>
> I note that the Map variant in the patch is a cunning way to beat the
> absence of a pair/tuple and generics, but it would require some
> thought before adoption in the JDK.
>
> Stephen
>
>
--
-- Howard.
More information about the lambda-dev
mailing list