/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2011, Benedikt Huber (benedikt@vmars.tuwien.ac.at)
This program 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 <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.common.misc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import com.jopdesign.common.misc.MiscUtils.F1;
/**
* Purpose: Utilities to lift Collection functionality to Iterable s and Iterator s
* @author Benedikt Huber (benedikt@vmars.tuwien.ac.at)
*
*/
public class Iterators {
/**
* Purpose: An empty iterator
*/
public final static class EmptyIterator<T> implements Iterator<T> {
@SuppressWarnings("rawtypes")
protected static final EmptyIterator ITERATOR = new EmptyIterator();
@SuppressWarnings("unchecked")
public static<T> Iterator<T> instance() { return ITERATOR; }
@Override
public boolean hasNext() {
return false;
}
@Override
public T next() {
return null;
}
@Override
public void remove() {
throw new RuntimeException("remove called on invalid iterator");
}
}
/**
* Purpose: Iterator for arrays
*/
public static class ArrayIterator<T> implements Iterator<T> {
private int ix;
private T[] arr;
public ArrayIterator(T[] arr) {
this.arr = arr;
this.ix = 0;
}
@Override
public boolean hasNext() {
return ix<arr.length;
}
@Override
public T next() {
T r = arr[ix];
ix++;
return r;
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove() not supported by ArrayIterator<T>");
}
}
/**
* Purpose: Iterator for the elements of an iterator of iterators
*/
public static class ConcatIterator<T> implements Iterator<T> {
private Iterator<? extends Iterable<T>> outerIterator;
private Iterator<T> innerIterator;
public ConcatIterator(Iterable<T>[] cs) {
this.outerIterator = new ArrayIterator<Iterable<T>>(cs);
this.innerIterator = EmptyIterator.instance();
}
public ConcatIterator(Iterable<? extends Iterable<T>> cs) {
this.outerIterator = cs.iterator();
this.innerIterator = EmptyIterator.instance();
}
@Override
public boolean hasNext() {
while(! innerIterator.hasNext()) {
if(! outerIterator.hasNext()) return false;
innerIterator = outerIterator.next().iterator();
}
return true;
}
@Override
public T next() {
if(! hasNext()) return null;
return innerIterator.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove() not supported by ConcatIterator");
}
}
/**
* Purpose: An iterator which applies a transformation to each input
*
*/
public static class MapEntriesIterator<S,T> implements Iterator<T> {
private Iterator<S> sourceIterator;
private F1<S, T> f;
public MapEntriesIterator(Iterable<S> source, F1<S,T> f) {
this.sourceIterator = source.iterator();
this.f = f;
}
@Override
public boolean hasNext() {
return sourceIterator.hasNext();
}
@Override
public T next() {
if(! hasNext()) return null;
return f.apply(sourceIterator.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove() not supported by MapEntriesIterator");
}
}
public static<T, C extends Collection<T>> C addAll(C coll, Iterable<? extends T> addme) {
for(T e : addme) { coll.add(e); }
return coll;
}
public static<T> Iterable<T> concat(final Iterable<? extends Iterable<T>> cs) {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new ConcatIterator<T>(cs);
}
};
}
public static<T> Iterable<T> concat(final Iterable<T> c1, final Iterable<T> c2) {
ArrayList<Iterable<T>> listOfLists = new ArrayList<Iterable<T>>(2);
listOfLists.add(c1);
listOfLists.add(c2);
return concat(listOfLists);
}
public static<T> Iterable<T> empty() {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return EmptyIterator.instance();
}
};
}
public static <S,T> Iterable<T> mapEntries(final Iterable<S> input, final F1<S,T> f) {
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new MapEntriesIterator<S, T>(input,f);
}
};
}
public static<T> Iterable<T> singleton(T elem) {
return Collections.singleton(elem);
}
/**
* if there is only one object in the iterable, return this object
* @param <T> type of the objects the Iterable returns
* @param coll the Iterable that will be traversed using iterator()
* @return the only object in the Iterable, or null if the Iterable
* contains no or more than one object
*/
public static<T> T fromSingleton(Iterable<T> coll) {
Iterator<T> iter = coll.iterator();
if(! iter.hasNext())
return null;
T obj = iter.next();
if(iter.hasNext())
return null;
return obj;
}
public static<T> int size(Iterable<T> nodes) {
int i = 0;
Iterator<T> iter = nodes.iterator();
while(iter.hasNext()) {
i++;
iter.next();
}
return i;
}
/**
* @param values a list of integers
* @return the sum of the given values
*/
public static long sum(Iterable<Long> values) {
long sum = 0;
for(long v : values) {
sum +=v;
}
return sum;
}
}