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

org.neo4j.helpers.collection.IteratorUtil Maven / Gradle / Ivy

Go to download

Neo4j kernel is a lightweight, embedded Java database designed to store data structured as graphs rather than tables. For more information, see http://neo4j.org.

There is a newer version: 5.26.0
Show newest version
/**
 * Copyright (c) 2002-2013 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 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, see .
 */
package org.neo4j.helpers.collection;

import static java.util.Arrays.asList;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * Contains common functionality regarding {@link Iterator}s and
 * {@link Iterable}s.
 */
public abstract class IteratorUtil
{
    /**
     * Returns the given iterator's first element or {@code null} if no
     * element found.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the first element in the {@code iterator}, or {@code null} if no
     * element found.
     */
    public static  T firstOrNull( Iterator iterator )
    {
        return iterator.hasNext() ? iterator.next() : null;
    }
    
    /**
     * Returns the given iterator's first element. If no element is found a
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the first element in the {@code iterator}.
     * @throws {@link NoSuchElementException} if no element found.
     */
    public static  T first( Iterator iterator )
    {
        return assertNotNull( iterator, firstOrNull( iterator ) );
    }
    
    /**
     * Returns the given iterator's last element or {@code null} if no
     * element found.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the last element in the {@code iterator}, or {@code null} if no
     * element found.
     */
    public static  T lastOrNull( Iterator iterator )
    {
        T result = null;
        while ( iterator.hasNext() )
        {
            result = iterator.next();
        }
        return result;
    }
    
    /**
     * Returns the given iterator's last element. If no element is found a
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the last element in the {@code iterator}.
     * @throws {@link NoSuchElementException} if no element found.
     */
    public static  T last( Iterator iterator )
    {
        return assertNotNull( iterator, lastOrNull( iterator ) );
    }
    
    /**
     * Returns the given iterator's single element or {@code null} if no
     * element found. If there is more than one element in the iterator a
     * {@link NoSuchElementException} will be thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the single element in {@code iterator}, or {@code null} if no
     * element found.
     * @throws {@link NoSuchElementException} if more than one element was
     * found.
     */
    public static  T singleOrNull( Iterator iterator )
    {
        T result = iterator.hasNext() ? iterator.next() : null;
        if ( iterator.hasNext() )
        {
            throw new NoSuchElementException( "More than one element in " +
                iterator + ". First element is '" + result +
                "' and the second element is '" + iterator.next() + "'" );
        }
        return result;
    }
    
    /**
     * Returns the given iterator's single element. If there are no elements
     * or more than one element in the iterator a {@link NoSuchElementException}
     * will be thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @return the single element in the {@code iterator}.
     * @throws {@link NoSuchElementException} if there isn't exactly one
     * element.
     */
    public static  T single( Iterator iterator )
    {
        return assertNotNull( iterator, singleOrNull( iterator ) );
    }
    
    /**
     * Returns the iterator's n:th item from the end of the iteration.
     * If the iterator has got less than n-1 items in it
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @param n the n:th item from the end to get.
     * @return the iterator's n:th item from the end of the iteration.
     * @throws NoSuchElementException if the iterator contains less than n-1 items.
     */
    public static  T fromEnd( Iterator iterator, int n )
    {
        return assertNotNull( iterator, fromEndOrNull( iterator, n ) );
    }

    /**
     * Returns the iterator's n:th item from the end of the iteration.
     * If the iterator has got less than n-1 items in it {@code null} is returned.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterator the {@link Iterator} to get elements from.
     * @param n the n:th item from the end to get.
     * @return the iterator's n:th item from the end of the iteration,
     * or {@code null} if the iterator doesn't contain that many items.
     */
    public static  T fromEndOrNull( Iterator iterator, int n )
    {
        Deque trail = new ArrayDeque( n );
        while ( iterator.hasNext() )
        {
            if ( trail.size() > n )
            {
                trail.removeLast();
            }
            trail.addFirst( iterator.next() );
        }
        return trail.size() == n + 1 ? trail.getLast() : null;
    }

    /**
     * Iterates over the full iterators, and checks equality for each item in them. Note that this
     * will consume the iterators.
     *
     * @param first
     * @param other
     * @return
     */
    public static boolean iteratorsEqual(Iterator first, Iterator other)
    {
        while(true)
        {
            if(first.hasNext() && other.hasNext())
            {
                if(!first.next().equals( other.next() ))
                {
                    return false;
                }
            } else
            {
                return first.hasNext() == other.hasNext();
            }
        }
    }

    private static  T assertNotNull( Iterator iterator, T result )
    {
        if ( result == null )
        {
            throw new NoSuchElementException( "No element found in " + iterator );
        }
        return result;
    }
    
    /**
     * Returns the given iterable's first element or {@code null} if no
     * element found.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the first element in the {@code iterable}, or {@code null} if no
     * element found.
     */
    public static  T firstOrNull( Iterable iterable )
    {
        return firstOrNull( iterable.iterator() );
    }
    
    /**
     * Returns the given iterable's first element. If no element is found a
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the first element in the {@code iterable}.
     * @throws {@link NoSuchElementException} if no element found.
     */
    public static  T first( Iterable iterable )
    {
        return first( iterable.iterator() );
    }
    
    /**
     * Returns the given iterable's last element or {@code null} if no
     * element found.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the last element in the {@code iterable}, or {@code null} if no
     * element found.
     */
    public static  T lastOrNull( Iterable iterable )
    {
        return lastOrNull( iterable.iterator() );
    }
    
    /**
     * Returns the given iterable's last element. If no element is found a
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the last element in the {@code iterable}.
     * @throws {@link NoSuchElementException} if no element found.
     */
    public static  T last( Iterable iterable )
    {
        return last( iterable.iterator() );
    }
    
    /**
     * Returns the given iterable's single element or {@code null} if no
     * element found. If there is more than one element in the iterable a
     * {@link NoSuchElementException} will be thrown.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the single element in {@code iterable}, or {@code null} if no
     * element found.
     * @throws {@link NoSuchElementException} if more than one element was
     * found.
     */
    public static  T singleOrNull( Iterable iterable )
    {
        return singleOrNull( iterable.iterator() );
    }
    
    /**
     * Returns the given iterable's single element. If there are no elements
     * or more than one element in the iterable a {@link NoSuchElementException}
     * will be thrown.
     * 
     * @param  the type of elements in {@code iterable}.
     * @param iterable the {@link Iterable} to get elements from.
     * @return the single element in the {@code iterable}.
     * @throws {@link NoSuchElementException} if there isn't exactly one
     * element.
     */
    public static  T single( Iterable iterable )
    {
        return single( iterable.iterator() );
    }
    
    /**
     * Returns the iterator's n:th item from the end of the iteration.
     * If the iterator has got less than n-1 items in it {@code null} is returned.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterable the {@link Iterable} to get elements from.
     * @param countFromEnd the n:th item from the end to get.
     * @return the iterator's n:th item from the end of the iteration,
     * or {@code null} if the iterator doesn't contain that many items.
     */
    public static  T fromEndOrNull( Iterable iterable, int countFromEnd )
    {
        return fromEndOrNull( iterable.iterator(), countFromEnd );
    }
    
    /**
     * Returns the iterator's n:th item from the end of the iteration.
     * If the iterator has got less than n-1 items in it
     * {@link NoSuchElementException} is thrown.
     * 
     * @param  the type of elements in {@code iterator}.
     * @param iterable the {@link Iterable} to get elements from.
     * @param n the n:th item from the end to get.
     * @return the iterator's n:th item from the end of the iteration.
     * @throws NoSuchElementException if the iterator contains less than n-1 items.
     */
    public static  T fromEnd( Iterable iterable, int n )
    {
        return fromEnd( iterable.iterator(), n );
    }
    
    /**
     * Adds all the items in {@code iterator} to {@code collection}.
     * @param  the type of {@link Collection} to add to items to.
     * @param  the type of items in the collection and iterator.
     * @param iterator the {@link Iterator} to grab the items from.
     * @param collection the {@link Collection} to add the items to.
     * @return the {@code collection} which was passed in, now filled
     * with the items from {@code iterator}.
     */
    public static ,T> C addToCollection( Iterator iterator,
            C collection )
    {
        while ( iterator.hasNext() )
        {
            collection.add( iterator.next() );
        }
        return collection;
    }

    /**
     * Adds all the items in {@code iterator} to {@code collection}.
     * @param  the type of {@link Collection} to add to items to.
     * @param  the type of items in the collection and iterator.
     * @param iterable the {@link Iterator} to grab the items from.
     * @param collection the {@link Collection} to add the items to.
     * @return the {@code collection} which was passed in, now filled
     * with the items from {@code iterator}.
     */
    public static ,T> C addToCollection( Iterable iterable,
            C collection )
    {
        return addToCollection(iterable.iterator(), collection);
    }

    /**
     * Convenience method for looping over an {@link Iterator}. Converts the
     * {@link Iterator} to an {@link Iterable} by wrapping it in an
     * {@link Iterable} that returns the {@link Iterator}. It breaks the
     * contract of {@link Iterable} in that it returns the supplied iterator
     * instance for each call to {@code iterator()} on the returned
     * {@link Iterable} instance. This method exists to make it easy to use an
     * {@link Iterator} in a for-loop.
     * 
     * @param  the type of items in the iterator.
     * @param iterator the iterator to expose as an {@link Iterable}.
     * @return the supplied iterator posing as an {@link Iterable}.
     */
    public static  Iterable loop( final Iterator iterator )
    {
        return new Iterable()
        {
            @Override
            public Iterator iterator()
            {
                return iterator;
            }
        };
    }
    
    /**
     * Exposes {@code iterator} as an {@link Iterable}. It breaks the contract
     * of {@link Iterable} in that it returns the supplied iterator instance for
     * each call to {@code iterator()} on the returned {@link Iterable}
     * instance. This method mostly exists to make it easy to use an
     * {@link Iterator} in a for-loop.
     * 
     * @param  the type of items in the iterator.
     * @param iterator the iterator to expose as an {@link Iterable}.
     * @return the supplied iterator posing as an {@link Iterable}.
     */
    //@Deprecated * @deprecated use {@link #loop(Iterator) the loop method} instead.
    public static  Iterable asIterable( final Iterator iterator )
    {
        return loop( iterator );
    }
    
    /**
     * Counts the number of items in the {@code iterator} by looping
     * through it.
     * @param  the type of items in the iterator.
     * @param iterator the {@link Iterator} to count items in.
     * @return the number of found in {@code iterator}.
     */
    public static  int count( Iterator iterator )
    {
        int result = 0;
        while ( iterator.hasNext() )
        {
            iterator.next();
            result++;
        }
        return result;
    }

    /**
     * Counts the number of items in the {@code iterable} by looping through it.
     * 
     * @param  the type of items in the iterator.
     * @param iterable the {@link Iterable} to count items in.
     * @return the number of found in {@code iterator}.
     */
    public static  int count( Iterable iterable )
    {
        return count( iterable.iterator() );
    }


    /**
     * Creates a collection from an iterable.
     *
     * @param iterable The iterable to create the collection from.
     * @param  The generic type of both the iterable and the collection.
     * @return a collection containing all items from the iterable.
     */
    public static  Collection asCollection( Iterable iterable )
    {
        List list = new ArrayList();
        addToCollection( iterable, list );
        return list;
    }
    
    /**
     * Creates a {@link Set} from an {@link Iterable}.
     *
     * @param iterable The items to create the set from.
     * @param  The generic type of items.
     * @return a set containing all items from the {@link Iterable}.
     */
    public static  Set asSet( Iterable iterable )
    {
        return addToCollection( iterable, new HashSet() );
    }

    /**
     * Creates a {@link Set} from an array of items.
     *
     * @param items the items to add to the set.
     * @return the {@link Set} containing the items.
     */
    public static  Set asSet( T... items )
    {
        return new HashSet( asList( items ) );
    }
    
    /**
     * Creates an {@link Iterable} for iterating over the lines of a text file.
     * @param file the file to get the lines for.
     * @return an {@link Iterable} for iterating over the lines of a text file.
     */
    public static ClosableIterable asIterable( final File file )
    {
        return new ClosableIterable()
        {
            private ClosableIterator mostRecentIterator;
            
            @Override
            public Iterator iterator()
            {
                try
                {
                    if ( mostRecentIterator != null ) mostRecentIterator.close();
                    mostRecentIterator = asIterator( file );
                    return mostRecentIterator;
                }
                catch ( IOException e )
                {
                    throw new RuntimeException( e );
                }
            }
            
            @Override
            public void close()
            {
                if ( mostRecentIterator != null ) mostRecentIterator.close();
            }
        };
    }
    
    /**
     * Creates an {@link Iterator} for iterating over the lines of a text file.
     * The opened file is closed if an exception occurs during reading or when
     * the files has been read through all the way.
     * @param file the file to get the lines for.
     * @return an {@link Iterator} for iterating over the lines of a text file.
     */
    public static ClosableIterator asIterator( File file ) throws IOException
    {
        return new LinesOfFileIterator( file );
    }
    
    public static  void streamToFile( Iterable iterable, File file, String encoding ) throws IOException
    {
        streamToFile( iterable.iterator(), file, encoding );
    }

    public static  void streamToFile( Iterator iterator, File file, String encoding ) throws IOException
    {
        if ( file.exists() ) throw new IOException( "File '" + file + "' already exists" );
        PrintStream out = null;
        try
        {
            out = new PrintStream( file, encoding );
            while ( iterator.hasNext() ) out.println( iterator.next().toString() );
        }
        finally
        {
            safeClose( out );
        }
    }
    
    private static void safeClose( Closeable closeable )
    {
        if ( closeable != null )
        {
            try
            {
                closeable.close();
            }
            catch ( IOException e )
            {
                // What can we do?
                e.printStackTrace();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy