/* * Copyright 2017 the original author or authors. * * Licensed 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.gradle.api.internal; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.TreeSet; public interface WithEstimatedSize { /** * Returns an estimate of the size of this collection or iterator. The idea is that this information * can be used internally to make better default dimensions for temporary objects. Therefore, it is * intended to return a value which is greater or equal to the real size (pessimistic). The typical use * case is creating a hash set or hash map of a collection without knowing the number of elements it * will contain. With this method we can properly size it and avoid resizes. The reason we use an * estimate size instead of the real size is that sometimes the real size is too expensive to compute. * Typically in a filtered collection you would have to actually do the filtering before knowing the size, * so killing all possible optimizations. Instead, it should return the size of the collection it wraps, * so that we have an estimate of the number of elements it may contain. The closer to reality is the better, * of course. * * @return the estimate size of the object */ int estimatedSize(); class Estimates { public static <T> int estimateSizeOf(Collection<T> collection) { if (isKnownToHaveConstantTimeSizeMethod(collection)) { return collection.size(); } if (collection instanceof WithEstimatedSize) { return ((WithEstimatedSize) collection).estimatedSize(); } return 10; // we don't know if the underlying collection can return a size in constant time } public static <T> boolean isKnownToHaveConstantTimeSizeMethod(Collection<T> collection) { Class<? extends Collection> clazz = collection.getClass(); if (clazz == HashSet.class || clazz == ArrayList.class || clazz == LinkedList.class || clazz == TreeSet.class) { return true; } return false; } } }