You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/04/12 11:25:27 UTC

[isis] 04/04: ISIS-1932 consolidate array & collection idioms

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 6031ebae610fe45ac6d331e2b420dc11186f9897
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 12 13:24:46 2018 +0200

    ISIS-1932 consolidate array & collection idioms
---
 .../isis/applib/internal/base/_NullSafe.java       |  16 ++
 .../internal/collections/_Array_Collector.java     |  99 ++++++++++++
 .../collections/_Array_CollectorUnknownSize.java   |  82 ++++++++++
 .../isis/applib/internal/collections/_Arrays.java  |  68 ++++++++-
 .../applib/internal/collections/_Collections.java  |  34 ++++-
 .../isis/applib/internal/collections/_Lists.java   |  11 ++
 .../isis/applib/internal/collections/_Sets.java    |  39 +++++
 .../core/metamodel/facets/CollectionUtils.java     | 168 ++++++++++-----------
 8 files changed, 424 insertions(+), 93 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
index 08cfef1..c6b4b99 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
@@ -23,6 +23,7 @@ import java.util.Comparator;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.Consumer;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -115,6 +116,21 @@ public final class _NullSafe {
 		return x==null;
 	}
 	
+	// -- PEEK OPERATOR
+	
+	/**
+	 * Unary identity operator that passes {@code obj} to {@code ifPresent} if {@code obj} is present.   
+	 * @param obj
+	 * @param ifPresent
+	 * @return {@code obj}
+	 */
+	public final static <T> T peek(T obj, Consumer<T> ifPresent) {
+		if(obj!=null) {
+			ifPresent.accept(obj);
+		}
+		return obj;
+	}
+	
 	// -- EQUALS/COMPARE
 	
 	/**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java
new file mode 100644
index 0000000..d0a7948
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java
@@ -0,0 +1,99 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.internal.collections;
+
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import org.apache.isis.applib.internal.base._Casts;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Arrays}
+ * 
+ * Collector for Arrays.
+ *
+ */
+class _Array_Collector<T> implements Collector<T, _Array_Collector.FastList<T>, T[]> {
+	
+	private final Class<T> componentType;
+	private final int size;
+	
+	_Array_Collector(Class<T> componentType, int size) {
+		this.componentType = componentType;
+		this.size = size;
+	}
+
+	@Override
+	public Supplier<FastList<T>> supplier() {
+		return ()->new FastList<>(componentType, size);
+	}
+
+	@Override
+	public BiConsumer<FastList<T>, T> accumulator() {
+		return FastList::add;
+	}
+
+	@Override
+	public BinaryOperator<FastList<T>> combiner() {
+		return (a,b)->a.addAll(b);
+	}
+
+	@Override
+	public Function<FastList<T>, T[]> finisher() {
+		return list->list.buffer;
+	}
+
+	@Override
+	public Set<Characteristics> characteristics() {
+		return Collections.emptySet();
+	}
+
+	// -- HELPER
+	
+	static final class FastList<T> {
+		private final T[] buffer;
+		private int offset=0;
+		
+		public FastList(Class<T> componentType, int size) {
+			this.buffer = _Casts.uncheckedCast(Array.newInstance(componentType, size));
+		}
+		public void add(T x){
+			buffer[offset++]=x;
+		}
+		public FastList<T> addAll(FastList<T> x){
+			System.arraycopy(x.buffer, 0, buffer, offset, x.offset);
+			return this;
+		}
+	}
+	
+	
+}
+
+
+	
+	
+
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java
new file mode 100644
index 0000000..c318f20
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java
@@ -0,0 +1,82 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.applib.internal.collections;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import org.apache.isis.applib.internal.base._Casts;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Arrays}
+ * 
+ * Collector for Arrays.
+ *
+ */
+class _Array_CollectorUnknownSize<T> implements Collector<T, List<T>, T[]> {
+	
+	private final Class<T> componentType;
+	
+	_Array_CollectorUnknownSize(Class<T> componentType) {
+		this.componentType = componentType;
+	}
+
+	@Override
+	public Supplier<List<T>> supplier() {
+		return ArrayList::new;
+	}
+
+	@Override
+	public BiConsumer<List<T>, T> accumulator() {
+		return List::add;
+	}
+
+	@Override
+	public BinaryOperator<List<T>> combiner() {
+		return (left, right) -> { left.addAll(right); return left; };
+	}
+
+	@Override
+	public Function<List<T>, T[]> finisher() {
+		final T[] arg = _Casts.uncheckedCast(Array.newInstance(componentType, 0));
+		return list->list.toArray(arg);
+	}
+
+	@Override
+	public Set<Characteristics> characteristics() {
+		return Collections.emptySet();
+	}
+	
+	
+}
+
+
+	
+	
+
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
index 4c59969..816aa06 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
@@ -19,8 +19,14 @@
 
 package org.apache.isis.applib.internal.collections;
 
+import java.util.Collection;
+import java.util.Objects;
+import java.util.stream.Collector;
+
 import javax.annotation.Nullable;
 
+import org.apache.isis.applib.internal.base._NullSafe;
+
 /**
  * <h1>- internal use only -</h1>
  * <p>
@@ -33,7 +39,9 @@ import javax.annotation.Nullable;
  * 
  * @since 2.0.0
  */
-public class _Arrays {
+public final class _Arrays {
+	
+	private _Arrays(){}
 	
     // -- PREDICATES
 
@@ -54,7 +62,63 @@ public class _Arrays {
     public static boolean isCollectionOrArrayType(final Class<?> cls) {
         return _Collections.isCollectionType(cls) || _Arrays.isArrayType(cls);
     }
-	
+    
+    // -- TO-ARRAY COLLECTORS
+    
+    /**
+     * Known-size Collector.
+     * @param componentType
+     * @param length
+     * @return
+     */
+    public static <T> Collector<T,?,T[]> toArray(final Class<T> componentType, final int length){
+    	Objects.requireNonNull(componentType);
+		return new _Array_Collector<T>(componentType, length);
+	}
+    
+    /**
+     * Unknown-size Collector.
+     * @param componentType
+     * @return
+     */
+    public static <T> Collector<T,?,T[]> toArray(final Class<T> componentType){
+    	Objects.requireNonNull(componentType);
+		return new _Array_CollectorUnknownSize<T>(componentType);
+	}
+
+    // -- CONSTRUCTION
+    
+    /**
+     * Copies a collection's elements into an array.
+     *
+     * @param iterable the iterable to copy
+     * @param type the type of the elements
+     * @return a newly-allocated array into which all the elements of the iterable
+     *     have been copied (non-null)
+     */
+	public static <T> T[] toArray(@Nullable final Collection<? extends T> collection, final Class<T> componentType) {
+		Objects.requireNonNull(componentType);
+		return _NullSafe.stream(collection)
+				.collect(toArray(componentType, collection!=null ? collection.size() : 0));
+	}
+    
+    /**
+     * Copies an iterable's elements into an array.
+     *
+     * @param iterable the iterable to copy
+     * @param type the type of the elements
+     * @return a newly-allocated array into which all the elements of the iterable
+     *     have been copied (non-null)
+     */
+	public static <T> T[] toArray(@Nullable final Iterable<? extends T> iterable, final Class<T> componentType) {
+		Objects.requireNonNull(componentType);
+		if(iterable!=null && (iterable instanceof Collection)) {
+			return toArray((Collection<? extends T>) iterable, componentType);
+		}
+		return _NullSafe.stream(iterable)
+				.collect(toArray(componentType));
+	}
+    
     // -- COMPONENT TYPE INFERENCE
     
     /**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
index 9d14b39..dd117f0 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
@@ -33,11 +33,15 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.stream.Collector;
 import java.util.stream.Collectors;
 
 import javax.annotation.Nullable;
 
+import org.apache.isis.applib.internal.base._NullSafe;
+
 /**
  * <h1>- internal use only -</h1>
  * <p>
@@ -50,7 +54,9 @@ import javax.annotation.Nullable;
  * 
  * @since 2.0.0
  */
-public class _Collections {
+public final class _Collections {
+	
+	private _Collections(){}
 	
     // -- PREDICATES
 
@@ -210,6 +216,32 @@ public class _Collections {
 						typeOfCollection.getClass().getName()));
 	}
 	
+	// -- COLLECT FROM ITERABLE
+	
+	/*
+	 * package private utility for a slightly heap pollution reduced collection, 
+	 * if the iterable is a collection and we know the size of the result in advance
+	 * 
+	 * @param iterable
+	 * @param factory
+	 * @param elementCollector
+	 * @return
+	 */
+	static <T, R> R collectFromIterable(
+			@Nullable Iterable<T> iterable, 
+			Function<Collection<T>, R> factory, 
+			Supplier<Collector<T, ?, R>> elementCollector) {
+		
+		if(iterable==null) {
+			return factory.apply(null);
+		}
+		if(iterable instanceof Collection) {
+			return factory.apply((Collection<T>) iterable);
+		}
+		return _NullSafe.stream(iterable)
+				.collect(elementCollector.get());
+	}
+	
 	// -- ELEMENT TYPE INFERENCE
 	
     /**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
index 6bf8059..e0e95cb 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
@@ -101,6 +101,11 @@ public final class _Lists {
 		return new ArrayList<T>(collection);
 	}
 	
+	public static <T> ArrayList<T> newArrayList(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Lists::newArrayList, 
+				()->Collectors.<T, ArrayList<T>>toCollection(ArrayList::new) );
+	}
+	
 	// -- LINKED LIST
 	
 	public static <T> LinkedList<T> newLinkedList() {
@@ -114,6 +119,11 @@ public final class _Lists {
 		return new LinkedList<T>(collection);
 	}
 	
+	public static <T> LinkedList<T> newLinkedList(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Lists::newLinkedList, 
+				()->Collectors.<T, LinkedList<T>>toCollection(LinkedList::new) );
+	}
+	
 	// -- TRANSFORMATION
 	
 	public static <T, R> List<R> transform(@Nullable List<T> input, Function<T, R> mapper) {
@@ -126,4 +136,5 @@ public final class _Lists {
 				.collect(Collectors.toList());
 	}
 	
+	
 }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
index 9abbc1e..6556fb9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
@@ -21,10 +21,12 @@ package org.apache.isis.applib.internal.collections;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap.KeySetView;
 import java.util.stream.Collectors;
@@ -76,6 +78,27 @@ public final class _Sets {
 				.collect(Collectors.toSet()));
 	}
 	
+	// -- TREE SET
+	
+	public static <T> TreeSet<T> newTreeSet() {
+		return new TreeSet<T>();
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Comparator<T> comparator) {
+		return comparator!=null ? new TreeSet<T>(comparator) : new TreeSet<T>();
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Iterable<T> iterable) {
+		return _NullSafe.stream(iterable)
+				.collect(Collectors.<T, TreeSet<T>>toCollection(TreeSet::new));
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Iterable<T> iterable, @Nullable Comparator<T> comparator) {
+		return _NullSafe.stream(iterable)
+				.collect(Collectors.<T, TreeSet<T>>toCollection(()->new TreeSet<T>(comparator)));
+	}
+	
+	
 	// -- HASH SET
 	
 	public static <T> HashSet<T> newHashSet() {
@@ -89,6 +112,11 @@ public final class _Sets {
 		return new HashSet<T>(collection);
 	}
 	
+	public static <T> HashSet<T> newHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newHashSet, 
+				()->Collectors.<T, HashSet<T>>toCollection(HashSet::new) );
+	}
+	
 	// -- LINKED HASH SET
 	
 	public static <T> LinkedHashSet<T> newLinkedHashSet() {
@@ -102,6 +130,11 @@ public final class _Sets {
 		return new LinkedHashSet<T>(collection);
 	}
 	
+	public static <T> LinkedHashSet<T> newLinkedHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newLinkedHashSet, 
+				()->Collectors.<T, LinkedHashSet<T>>toCollection(LinkedHashSet::new) );
+	}
+	
 	// -- CONCURRENT HASH SET
 	
 	public static <T> KeySetView<T, Boolean> newConcurrentHashSet() {
@@ -116,6 +149,12 @@ public final class _Sets {
 		return keySetView;
 	}
 	
+	public static <T> KeySetView<T, Boolean> newConcurrentHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newConcurrentHashSet, 
+				()->Collectors.<T, KeySetView<T, Boolean>>toCollection(ConcurrentHashMap::newKeySet) );
+	}
+	
+	
 	// -- SET OPERATIONS
 
 	/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
index 033d4b3..8c188da 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
@@ -23,110 +23,98 @@ import java.util.AbstractList;
 import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.function.Function;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
+import org.apache.isis.applib.internal.base._Casts;
+import org.apache.isis.applib.internal.base._NullSafe;
+import org.apache.isis.applib.internal.collections._Arrays;
+import org.apache.isis.applib.internal.collections._Lists;
+import org.apache.isis.applib.internal.collections._Sets;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 public final class CollectionUtils {
-    private CollectionUtils() {
-    }
-
-    public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final AdapterManager adapterMap) {
-        final ObjectAdapter collection = adapterMap.adapterFor(option);
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
-        final Object[] optionArray = new Object[facet.size(collection)];
-        int j = 0;
-        for (final ObjectAdapter nextElement : facet.iterable(collection)) {
-            optionArray[j++] = nextElement != null? nextElement.getObject(): null;
-        }
-        return optionArray;
-    }
-
-    /**
-     * Copies the iterable into the specified type.
-     */
-    public static Object copyOf(final Iterable<Object> iterable, final Class<?> requiredType) {
-
-        if(iterable == null) {
-            throw new IllegalArgumentException("Iterable must be provided");
-        }
-        if(requiredType == null) {
-            throw new IllegalArgumentException("RequiredType must be provided");
-        }
-
-        // specific list implementations
-        if (CopyOnWriteArrayList.class == requiredType) {
-            return Lists.newCopyOnWriteArrayList(iterable);
-        }
-        if (LinkedList.class == requiredType) {
-            return Lists.newLinkedList(iterable);
-        }
-        if (ArrayList.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        if (AbstractList.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        // specific set implementations
-        if (CopyOnWriteArraySet.class == requiredType) {
-            return Sets.newCopyOnWriteArraySet(iterable);
-        }
-        if (LinkedHashSet.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-        if (HashSet.class == requiredType) {
-            return Sets.newHashSet(iterable);
-        }
-        if (TreeSet.class == requiredType) {
-            Iterable rawIterable = iterable;
-            return Sets.newTreeSet(rawIterable);
-        }
-
-        if (AbstractSet.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-
-
-        // interfaces
-        if (List.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-        if (SortedSet.class == requiredType) {
-            Iterable rawIterable = iterable;
-            return Sets.newTreeSet(rawIterable);
-        }
-        if (Set.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-        if (Collection.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        // array
-        if (requiredType.isArray()) {
-            Class<?> componentType = requiredType.getComponentType();
-            Iterable rawIterable = iterable;
-            return Iterables.toArray(rawIterable, componentType);
-        }
-
-        // not recognized
-        return null;
-    }
+
+	private CollectionUtils() {
+	}
+
+	public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final AdapterManager adapterMap) {
+		final ObjectAdapter collection = adapterMap.adapterFor(option);
+		final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
+		final Object[] optionArray = new Object[facet.size(collection)];
+		int j = 0;
+		for (final ObjectAdapter nextElement : facet.iterable(collection)) {
+			optionArray[j++] = nextElement != null? nextElement.getObject(): null;
+		}
+		return optionArray;
+	}
+
+	private final static Map<Class<?>, Function<Iterable<Object>, Object>> factoriesByType = _NullSafe.peek(
+			new HashMap<>(), map-> {
+				// specific list implementations
+				map.put(CopyOnWriteArrayList.class, Lists::newCopyOnWriteArrayList);
+				map.put(LinkedList.class, _Lists::newLinkedList);
+				map.put(ArrayList.class, _Lists::newArrayList);
+				map.put(AbstractList.class, _Lists::newArrayList);
+
+				// specific set implementations
+				map.put(CopyOnWriteArraySet.class, Sets::newCopyOnWriteArraySet);
+				map.put(LinkedHashSet.class, _Sets::newLinkedHashSet);
+				map.put(HashSet.class, _Sets::newHashSet);
+				map.put(TreeSet.class, _Sets::newTreeSet);
+				map.put(AbstractSet.class, _Sets::newLinkedHashSet);
+
+				// interfaces
+				map.put(List.class, _Lists::newArrayList);
+				map.put(SortedSet.class, _Sets::newTreeSet);
+				map.put(Set.class, _Sets::newLinkedHashSet);
+				map.put(Collection.class, _Lists::newArrayList);
+			});
+
+	/**
+	 * Copies the iterable into the specified type.
+	 */
+	public static Object copyOf(final Iterable<Object> iterable, final Class<?> requiredType) {
+
+		if(iterable == null) {
+			throw new IllegalArgumentException("Iterable must be provided");
+		}
+		if(requiredType == null) {
+			throw new IllegalArgumentException("RequiredType must be provided");
+		}
+
+		final Function<Iterable<Object>, Object> factory = factoriesByType.get(requiredType);
+		if(factory!=null) {
+			return factory.apply(iterable);
+		}
+
+		// array
+		if (requiredType.isArray()) {
+			Class<?> componentType = requiredType.getComponentType();
+			
+			@SuppressWarnings("rawtypes") Iterable rawIterable = iterable;
+			return _Arrays.toArray(_Casts.uncheckedCast(rawIterable), componentType);
+		}
+
+		// not recognized
+		return null;
+
+	}
+
 }

-- 
To stop receiving notification emails like this one, please contact
ahuber@apache.org.