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

aQute.lib.collections.Iterables Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package aQute.lib.collections;

import static java.util.Collections.emptyEnumeration;
import static java.util.Objects.requireNonNull;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators.AbstractSpliterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class Iterables {
	private Iterables() {}

	private static class Distinct implements Iterable {
		private final Set					first;
		private final Iterable				second;
		private final Function	mapper;
		private final Predicate				filter;

		Distinct(Set first, Iterable second, Function mapper,
			Predicate filter) {
			this.first = requireNonNull(first);
			this.second = requireNonNull(second);
			this.mapper = requireNonNull(mapper);
			this.filter = requireNonNull(filter);
		}

		@Override
		public void forEach(Consumer action) {
			requireNonNull(action);
			Iterator it1 = first.iterator();
			Iterator it2 = second.iterator();
			it1.forEachRemaining((T t) -> {
				R r = mapper.apply(t);
				if (filter.test(r)) {
					action.accept(r);
				}
			});
			it2.forEachRemaining((T t) -> {
				R r = mapper.apply(t);
				if (filter.test(r) && !first.contains(t)) {
					action.accept(r);
				}
			});
		}

		@Override
		public Iterator iterator() {
			return new Iterator() {
				private final Iterator	it1		= first.iterator();
				private final Iterator	it2		= second.iterator();
				private boolean						hasNext	= false;
				private R							next;

				@Override
				public boolean hasNext() {
					if (hasNext) {
						return true;
					}
					while (it1.hasNext()) {
						T t = it1.next();
						R r = mapper.apply(t);
						if (filter.test(r)) {
							next = r;
							return hasNext = true;
						}
					}
					while (it2.hasNext()) {
						T t = it2.next();
						R r = mapper.apply(t);
						if (filter.test(r) && !first.contains(t)) {
							next = r;
							return hasNext = true;
						}
					}
					return false;
				}

				@Override
				public R next() {
					if (hasNext()) {
						hasNext = false;
						return next;
					}
					throw new NoSuchElementException();
				}
			};
		}

		@Override
		public Spliterator spliterator() {
			Spliterator it1 = first.spliterator();
			Spliterator it2 = second.spliterator();
			long est = it1.estimateSize() + it2.estimateSize();
			int characteristics = Spliterator.DISTINCT;
			if (est < 0) {
				est = Long.MAX_VALUE;
			} else {
				characteristics |= Spliterator.SIZED;
			}
			if (it1.hasCharacteristics(Spliterator.ORDERED)) {
				characteristics |= Spliterator.ORDERED;
			}
			return new AbstractSpliterator(est, characteristics) {
				@Override
				public boolean tryAdvance(Consumer action) {
					requireNonNull(action);
					if (it1.tryAdvance((T t) -> {
						R r = mapper.apply(t);
						if (filter.test(r)) {
							action.accept(r);
						}
					})) {
						return true;
					}
					return it2.tryAdvance((T t) -> {
						R r = mapper.apply(t);
						if (filter.test(r) && !first.contains(t)) {
							action.accept(r);
						}
					});
				}
			};
		}
	}

	public static  Iterable distinct(Set first, Iterable second) {
		return new Distinct<>(first, second, t -> t, t -> true);
	}

	public static  Iterable distinct(Set first, Iterable second,
		Function mapper) {
		return new Distinct<>(first, second, mapper, r -> true);
	}

	public static  Iterable distinct(Set first, Iterable second,
		Function mapper, Predicate filter) {
		return new Distinct<>(first, second, mapper, filter);
	}

	private static class IterableEnumeration implements Iterable {
		private final Enumeration			enumeration;
		private final Function	mapper;
		private final Predicate				filter;
		private final AtomicBoolean						consume	= new AtomicBoolean();

		IterableEnumeration(Enumeration enumeration, Function mapper,
			Predicate filter) {
			this.enumeration = enumeration != null ? enumeration : emptyEnumeration();
			this.mapper = requireNonNull(mapper);
			this.filter = requireNonNull(filter);
		}

		private void consume() {
			if (consume.compareAndSet(false, true)) {
				return;
			}
			throw new IllegalStateException("enumeration already consumed");
		}

		@Override
		public void forEach(Consumer action) {
			requireNonNull(action);
			consume();
			while (enumeration.hasMoreElements()) {
				T t = enumeration.nextElement();
				R r = mapper.apply(t);
				if (filter.test(r)) {
					action.accept(r);
				}
			}
		}

		@Override
		public Iterator iterator() {
			consume();
			return new Iterator() {
				private boolean	hasNext	= false;
				private R		next;

				@Override
				public boolean hasNext() {
					if (hasNext) {
						return true;
					}
					while (enumeration.hasMoreElements()) {
						T t = enumeration.nextElement();
						R r = mapper.apply(t);
						if (filter.test(r)) {
							next = r;
							return hasNext = true;
						}
					}
					return false;
				}

				@Override
				public R next() {
					if (hasNext()) {
						hasNext = false;
						return next;
					}
					throw new NoSuchElementException();
				}
			};
		}

		@Override
		public Spliterator spliterator() {
			consume();
			return new AbstractSpliterator(Long.MAX_VALUE, Spliterator.ORDERED) {
				@Override
				public boolean tryAdvance(Consumer action) {
					requireNonNull(action);
					if (enumeration.hasMoreElements()) {
						T t = enumeration.nextElement();
						R r = mapper.apply(t);
						if (filter.test(r)) {
							action.accept(r);
						}
						return true;
					}
					return false;
				}
			};
		}
	}

	public static  Iterable iterable(Enumeration enumeration) {
		return new IterableEnumeration<>(enumeration, t -> t, t -> true);
	}

	public static  Iterable iterable(Enumeration enumeration,
		Function mapper) {
		return new IterableEnumeration<>(enumeration, mapper, r -> true);
	}

	public static  Iterable iterable(Enumeration enumeration,
		Function mapper, Predicate filter) {
		return new IterableEnumeration<>(enumeration, mapper, filter);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy