All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.commons.util.CollectionFactory Maven / Gradle / Ivy

There is a newer version: 9.1.7.Final
Show newest version
package org.infinispan.commons.util;

import org.infinispan.commons.equivalence.AnyEquivalence;
import org.infinispan.commons.equivalence.Equivalence;
import org.infinispan.commons.equivalence.EquivalentHashMap;
import org.infinispan.commons.equivalence.EquivalentHashSet;
import org.infinispan.commons.equivalence.EquivalentLinkedHashMap;
import org.infinispan.commons.util.concurrent.jdk8backported.ConcurrentParallelHashMapV8;
import org.infinispan.commons.util.concurrent.jdk8backported.EquivalentConcurrentHashMapV8;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * A factory for ConcurrentMaps.
 *
 * @author Manik Surtani
 * @author Galder Zamarreño
 * @since 5.1
 */
public class CollectionFactory {
   
   private static final ConcurrentMapCreator MAP_CREATOR;

   private static interface ConcurrentMapCreator {
       ConcurrentMap createConcurrentMap();
       ConcurrentMap createConcurrentMap(int initialCapacity);
       ConcurrentMap createConcurrentMap(int initialCapacity, int concurrencyLevel);
       ConcurrentMap createConcurrentParallelMap(int initialCapacity, int concurrencyLevel);
       ConcurrentMap createConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel);
   }

   private static class JdkConcurrentMapCreator implements ConcurrentMapCreator {

      @Override
      public  ConcurrentMap createConcurrentMap() {
         return new ConcurrentHashMap();
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity) {
         return new ConcurrentHashMap(initialCapacity);
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity, int concurrencyLevel) {
         return new ConcurrentHashMap(initialCapacity, 0.75f, concurrencyLevel);
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
         return new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel);
      }

      @Override
      public  ConcurrentMap createConcurrentParallelMap(int initialCapacity, int concurrencyLevel) {
         // by the time we baseline on JDK8 this code will be either dropped or adjusted, 
         //for now we need to use ConcurrentParallelHashMapV8
         return new ConcurrentParallelHashMapV8(initialCapacity, AnyEquivalence.getInstance(),
               AnyEquivalence.getInstance());
      }
   }

   private static class BackportedV8ConcurrentMapCreator implements ConcurrentMapCreator {

      @Override
      public  ConcurrentMap createConcurrentMap() {
         return new EquivalentConcurrentHashMapV8(
               AnyEquivalence.getInstance(), AnyEquivalence.getInstance());
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity) {
         return new EquivalentConcurrentHashMapV8(initialCapacity,
               AnyEquivalence.getInstance(), AnyEquivalence.getInstance());
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity, int concurrencyLevel) {
         return new EquivalentConcurrentHashMapV8(initialCapacity, 0.75f,
               concurrencyLevel, AnyEquivalence.getInstance(), AnyEquivalence.getInstance());
      }

      @Override
      public  ConcurrentMap createConcurrentMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
         return new EquivalentConcurrentHashMapV8(initialCapacity, loadFactor,
               concurrencyLevel, AnyEquivalence.getInstance(), AnyEquivalence.getInstance());
      }

      @Override
      public  ConcurrentMap createConcurrentParallelMap(int initialCapacity, int concurrencyLevel) {
         return new ConcurrentParallelHashMapV8(initialCapacity, 0.75f,
               concurrencyLevel, AnyEquivalence.getInstance(), AnyEquivalence.getInstance());
      }
   }
   
   static {
      boolean sunIncompatibleJvm;
      boolean jdk8;
      boolean allowExperimentalMap = Boolean.parseBoolean(System.getProperty("infinispan.unsafe.allow_jdk8_chm", "true"));

      try {
         Class.forName("sun.misc.Unsafe");
         sunIncompatibleJvm = false;
      } catch (ClassNotFoundException e) {
         sunIncompatibleJvm = true;
      }
      
      try {
         Class.forName("java.util.concurrent.atomic.LongAdder");
         jdk8 = true;
      } catch (ClassNotFoundException e) {
         jdk8 = false;
      }

      if (jdk8 || sunIncompatibleJvm || !allowExperimentalMap)
         MAP_CREATOR = new JdkConcurrentMapCreator();
      else
         MAP_CREATOR = new BackportedV8ConcurrentMapCreator();
   }
   
   public static  ConcurrentMap makeConcurrentMap() {
      return MAP_CREATOR.createConcurrentMap();
   }

   public static  ConcurrentMap makeConcurrentMap(int initCapacity) {
      return MAP_CREATOR.createConcurrentMap(initCapacity);
   }

   public static  ConcurrentMap makeConcurrentMap(int initCapacity, int concurrencyLevel) {
      return MAP_CREATOR.createConcurrentMap(initCapacity, concurrencyLevel);
   }
   
   public static  ConcurrentMap makeConcurrentParallelMap(int initCapacity, int concurrencyLevel) {
      return MAP_CREATOR.createConcurrentParallelMap(initCapacity, concurrencyLevel);
   }

   public static  ConcurrentMap makeConcurrentMap(int initCapacity, float loadFactor, int concurrencyLevel) {
      return MAP_CREATOR.createConcurrentMap(initCapacity, loadFactor, concurrencyLevel);
   }

   public static  ConcurrentMap makeConcurrentMap(
         Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentConcurrentHashMapV8(keyEq, valueEq);
      else
         return MAP_CREATOR.createConcurrentMap();
   }

   public static  ConcurrentMap makeConcurrentMap(
         int initCapacity, Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentConcurrentHashMapV8(initCapacity, keyEq, valueEq);
      else
         return MAP_CREATOR.createConcurrentMap(initCapacity);
   }

   public static  ConcurrentMap makeConcurrentMap(
         int initCapacity, int concurrencyLevel, Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentConcurrentHashMapV8(
               initCapacity, concurrencyLevel, keyEq, valueEq);
      else
         return MAP_CREATOR.createConcurrentMap(initCapacity, concurrencyLevel);
   }
   
   public static  ConcurrentMap makeConcurrentParallelMap(
         int initCapacity, int concurrencyLevel, Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new ConcurrentParallelHashMapV8(
               initCapacity, concurrencyLevel, keyEq, valueEq);
      else
         return MAP_CREATOR.createConcurrentParallelMap(initCapacity, concurrencyLevel);
   }

   public static  ConcurrentMap makeConcurrentMap(
         int initCapacity, float loadFactor, int concurrencyLevel,
         Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentConcurrentHashMapV8(
               initCapacity, loadFactor, concurrencyLevel, keyEq, valueEq);
      else
         return MAP_CREATOR.createConcurrentMap(initCapacity, loadFactor, concurrencyLevel);
   }

   public static  Map makeMap(
         Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentHashMap(keyEq, valueEq);
      else
         return new HashMap();
   }

   public static  Map makeMap(
         int initialCapacity, Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentHashMap(initialCapacity, keyEq, valueEq);
      else
         return new HashMap(initialCapacity);
   }

   public static  Map makeMap(
         Map entries, Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentHashMap(entries, keyEq, valueEq);
      else
         return new HashMap(entries);
   }

   public static  Map makeLinkedMap(int initialCapacity,
         float loadFactor, EquivalentLinkedHashMap.IterationOrder iterationOrder,
         Equivalence keyEq, Equivalence valueEq) {
      if (requiresEquivalent(keyEq, valueEq))
         return new EquivalentLinkedHashMap(initialCapacity, loadFactor, iterationOrder, keyEq, valueEq);
      else
         return new LinkedHashMap(initialCapacity, loadFactor, iterationOrder.toJdkAccessOrder());
   }

   public static  Set makeSet(Equivalence entryEq) {
      if (requiresEquivalent(entryEq))
         return new EquivalentHashSet(entryEq);
      else
         return new HashSet();
   }

   public static  Set makeSet(int initialCapacity, Equivalence entryEq) {
      if (requiresEquivalent(entryEq))
         return new EquivalentHashSet(initialCapacity, entryEq);
      else
         return new HashSet(initialCapacity);
   }

   /**
    * Create a Set backed by the specified array.
    *
    * @param entries the array by which the list will be backed
    * @param  type of elements
    * @return a set view of the specified array
    */
   public static  Set makeSet(T... entries) {
      return new HashSet(Arrays.asList(entries));
   }

   private static  boolean requiresEquivalent(
         Equivalence keyEq, Equivalence valueEq) {
      AnyEquivalence instance = AnyEquivalence.getInstance();
      return keyEq != instance || valueEq != instance;
   }

   private static  boolean requiresEquivalent(Equivalence typeEq) {
      return typeEq != AnyEquivalence.getInstance();
   }

}