Re: JEP 186: Collection Literals

Timo Kinnunen timo.kinnunen at gmail.com
Sat Jan 18 06:01:09 PST 2014


As long as the class file isn’t recompiled, then support of serialization of lambdas should provide a reasonably practically reliable guarantee.






-- 
Have a nice day,
Timo.

Sent from Windows Mail





From: Zhong Yu
Sent: ‎Saturday‎, ‎January‎ ‎18‎, ‎2014 ‎15‎:‎55
To: Peter Levart
Cc: lambda-dev at openjdk.java.net





On Sat, Jan 18, 2014 at 5:16 AM, Peter Levart <peter.levart at gmail.com> wrote:
>
> On 01/16/2014 12:43 AM, Remi Forax wrote:
>> We can also use the Builder Pattern of Ruby now that we have a lambda syntax
>>     new ArrayList<>(builder -> builder.add(1).add(2).add(3));
>>
>> Rémi
>
> This one is interesting, because it shows what can be achieved with
> lambdas today. It enables expressions that evaluate into singleton
> objects (like non-capturing lambdas). If the lambda body is
> non-capturing, it evaluates into constant singleton in current
> implementation. So objects produced with such lambdas can be cached
> (using lambda object as a weak key). Here's a sample test that exercises

Is this guaranteed? i.e. the same lambda object will behave the same
over the time?

> that:
>
> public class Test {
>      public static void main(String[] args) {
>          for (int i = 0; i < 3; i++) {
>              List<Double> list = immutableList(b -> b._(3.14)._(0.33333));
>              System.out.println(list + " : " +
> System.identityHashCode(list));
>          }
>          System.out.println();
>          for (int i = 0; i < 3; i++) {
>              double x = i;
>              List<Double> list = immutableList(b ->
> b._(3.14)._(0.33333)._(x));
>              System.out.println(list + " : " +
> System.identityHashCode(list));
>          }
>          System.out.println();
>          for (int i = 0; i < 3; i++) {
>              Map<String, Integer> map = immutableMap(b -> b._("aa",
> 1)._("bb", 2)._("cc", 3));
>              System.out.println(map + " : " + System.identityHashCode(map));
>          }
>          System.out.println();
>          for (int i = 0; i < 3; i++) {
>              int x = i;
>              Map<String, Integer> map = immutableMap(b -> b._("aa",
> 1)._("bb", 2)._("cc", x));
>              System.out.println(map + " : " + System.identityHashCode(map));
>          }
>      }
> }
>
> which prints:
>
> [3.14, 0.33333] : 1706377736
> [3.14, 0.33333] : 1706377736
> [3.14, 0.33333] : 1706377736
>
> [3.14, 0.33333, 0.0] : 868693306
> [3.14, 0.33333, 1.0] : 989110044
> [3.14, 0.33333, 2.0] : 321001045
>
> {aa=1, bb=2, cc=3} : 1044036744
> {aa=1, bb=2, cc=3} : 1044036744
> {aa=1, bb=2, cc=3} : 1044036744
>
> {aa=1, bb=2, cc=0} : 1915318863
> {aa=1, bb=2, cc=1} : 295530567
> {aa=1, bb=2, cc=2} : 1324119927
>
>
>
> Regards, Peter
>
>
> P.S. Here's what I used to compile above test:
>
> public interface Builder<T> extends Consumer<T> {
>      default Builder<T> _(T t) {
>          accept(t);
>          return this;
>      }
> }
>
> public interface BiBuilder<T, U> extends BiConsumer<T, U> {
>      default BiBuilder<T, U> _(T t, U u) {
>          accept(t, u);
>          return this;
>      }
> }
>
> public class Collections2 {
>
>      public static <T> ArrayList<T> arrayList(Consumer<Builder<T>>
> producer) {
>          ArrayList<T> list = new ArrayList<>();
>          producer.accept(list::add);
>          return list;
>      }
>
>      // cache of immutable lists per producer
>      private static final Map<Consumer<? extends Builder<?>>, List<?>>
> INTERNED_IMMUTABLE_LISTS = new WeakHashMap<>();
>
>      public static <T> List<T> immutableList(Consumer<Builder<T>>
> producer) {
>          synchronized (INTERNED_IMMUTABLE_LISTS) {
>              // check if already interned
>              @SuppressWarnings("unchecked")
>              List<T> list = (List<T>)
> INTERNED_IMMUTABLE_LISTS.get(producer);
>              if (list != null) return list;
>          }
>
>          // count elements produced
>          final int[] count = new int[1];
>          producer.accept(t -> count[0]++);
>
>          // construct new list
>          ArrayList<T> aList = new ArrayList<>(count[0]);
>          producer.accept(aList::add);
>
>          synchronized (INTERNED_IMMUTABLE_LISTS) {
>              // recheck (highly unlikely)
>              @SuppressWarnings("unchecked")
>              List<T> list = (List<T>)
> INTERNED_IMMUTABLE_LISTS.get(producer);
>              if (list != null) return list;
>              // put it into cache and return
>              list = Collections.unmodifiableList(aList);
>              INTERNED_IMMUTABLE_LISTS.put(producer, list);
>              return list;
>          }
>      }
>
>      public static <K, V> HashMap<K, V> hashMap(Consumer<BiBuilder<K,
> V>> producer) {
>          HashMap<K, V> map = new HashMap<>();
>          producer.accept(map::put);
>          return map;
>      }
>
>      // cache of immutable maps per producer
>      private static final Map<Consumer<? extends BiBuilder<?, ?>>,
> Map<?, ?>> INTERNED_IMMUTABLE_MAPS = new WeakHashMap<>();
>
>      public static <K, V> Map<K, V> immutableMap(Consumer<BiBuilder<K,
> V>> producer) {
>          synchronized (INTERNED_IMMUTABLE_MAPS) {
>              // check if already interned
>              @SuppressWarnings("unchecked")
>              Map<K, V> map = (Map<K, V>)
> INTERNED_IMMUTABLE_MAPS.get(producer);
>              if (map != null) return map;
>          }
>
>          // count elements produced
>          final int[] count = new int[1];
>          producer.accept((k, v) -> count[0]++);
>
>          // construct new map
>          HashMap<K, V> hMap = new HashMap<>(count[0] * 4 / 3);
>          producer.accept(hMap::put);
>
>          synchronized (INTERNED_IMMUTABLE_MAPS) {
>              // recheck (highly unlikely)
>              @SuppressWarnings("unchecked")
>              Map<K, V> map = (Map<K, V>)
> INTERNED_IMMUTABLE_MAPS.get(producer);
>              if (map != null) return map;
>              // put it into cache and return
>              map = Collections.unmodifiableMap(hMap);
>              INTERNED_IMMUTABLE_MAPS.put(producer, map);
>              return map;
>          }
>      }
> }
>
>
>


More information about the lambda-dev mailing list