org.grouplens.lenskit.collections.CollectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.grouplens.lenskit.collections.CollectionUtils.java

Source

/*
 * LensKit, an open source recommender systems toolkit.
 * Copyright 2010-2014 LensKit Contributors.  See CONTRIBUTORS.md.
 * Work on LensKit has been funded by the National Science Foundation under
 * grants IIS 05-34939, 08-08692, 08-12148, and 10-17697.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
/**
 *
 */
package org.grouplens.lenskit.collections;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterators;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.ObjectCollection;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.grouplens.lenskit.cursors.Cursor;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import static it.unimi.dsi.fastutil.longs.Long2DoubleMap.FastEntrySet;

/**
 * Various helper methods for working with collections (particularly Fastutil
 * collections).
 *
 * @author <a href="http://www.grouplens.org">GroupLens Research</a>
 * @compat Public
 */
public final class CollectionUtils {
    private CollectionUtils() {
    }

    /**
     * Use the fast iterator of an iterable, if available.
     *
     * @param <E>  The type of object to iterate.
     * @param iter An iterable to wrap
     * @return An iterable using the underlying iterable's fast iterator, if present,
     *         to do iteration. Fast iteration is detected by looking for a {@code fastIterator()}
     *         method, like is present in {@link FastEntrySet}.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <E> Iterable<E> fast(final Iterable<E> iter) {
        if (iter instanceof FastIterable) {
            return new Iterable<E>() {
                @Override
                public Iterator<E> iterator() {
                    return ((FastIterable) iter).fastIterator();
                }
            };
        } else if (iter instanceof Cursor) {
            return ((Cursor<E>) iter).fast();
        } else {
            Optional<Method> fastMethod = fastIteratorMethods.getUnchecked(iter.getClass());
            if (fastMethod.isPresent()) {
                final Method method = fastMethod.get();
                return new Iterable<E>() {
                    @Override
                    public Iterator<E> iterator() {
                        try {
                            return (Iterator<E>) method.invoke(iter);
                        } catch (IllegalAccessException e) {
                            return iter.iterator();
                        } catch (InvocationTargetException e) {
                            throw Throwables.propagate(e.getCause());
                        }
                    }
                };
            } else {
                return iter;
            }
        }
    }

    /**
     * Fast-aware filter-and-limit operation, filtering an iterable.  If the underlying iterable
     * does not support fast iteration, then the returned iterable's fast iteration will fall back
     * to ordinary iteration.
     *
     * @param iter The iterable to filter and limit.
     * @param pred The predicate for filtering.
     * @param limit The maximum number of items to return (negative for unlimited).
     * @param <E> The type of data in the iterable.
     * @return A fast iterable filtering and limiting.
     */
    public static <E> FastIterable<E> fastFilterAndLimit(Iterable<E> iter, Predicate<? super E> pred, int limit) {
        return new FilteringFastIterable<E>(iter, pred, limit);
    }

    /**
     * Cache of fast iterator methods for various classes.
     */
    private static final LoadingCache<Class<?>, Optional<Method>> fastIteratorMethods = CacheBuilder.newBuilder()
            .build(new CacheLoader<Class<?>, Optional<Method>>() {
                @Override
                public Optional<Method> load(Class<?> key) {
                    return Optional.fromNullable(MethodUtils.getAccessibleMethod(key, "fastIterator"));
                }
            });

    /**
     * Wrap a {@link Collection} in an {@link ObjectCollection}.
     * @param objects The collection of objects.
     * @param <E> The type of objects.
     * @return The collection as an {@link ObjectCollection}.
     */
    public static <E> ObjectCollection<E> objectCollection(Collection<E> objects) {
        if (objects instanceof ObjectCollection) {
            return (ObjectCollection<E>) objects;
        } else {
            return new ObjectCollectionWrapper<E>(objects);
        }
    }

    /**
     * Return a list that repeats a single object multiple times.
     *
     * @param obj The object.
     * @param n   The size of the list.
     * @param <T> The type of list elements.
     * @return A list containing {@var obj} {@var n} times.
     */
    public static <T> List<T> repeat(T obj, int n) {
        return new RepeatedList<T>(obj, n);
    }

    /**
     * Create an empty, immutable fast collection.
     *
     * @param <E> The type of fast collection.
     * @return An empty fast collection.
     * @deprecated Just use a standard empty collection.
     */
    @Deprecated
    public static <E> FastCollection<E> emptyFastCollection() {
        return new EmptyFastCollection<E>();
    }

    private static class EmptyFastCollection<E> extends AbstractCollection<E> implements FastCollection<E> {
        @Override
        public Iterator<E> fastIterator() {
            return Iterators.emptyIterator();
        }

        @Override
        public Iterator<E> iterator() {
            return Iterators.emptyIterator();
        }

        @Override
        public int size() {
            return 0;
        }
    }

    /**
     * Create an {@link IntList} that contains all numbers in a specified interval.
     * @param from The first number (inclusive)
     * @param to the last number (exclusive).
     * @return A list containing the integers in the interval {@code [from,to)}.
     */
    public static IntList interval(int from, int to) {
        Preconditions.checkArgument(to >= from, "last integer less than first");
        return new IntIntervalList(from, to);
    }
}