package com.taobao.atlas.dex.util; import java.util.Comparator; import java.util.Iterator; import java.util.PriorityQueue; import java.util.Queue; /** * 遍历工具类 * Created by shenghua.nish on 2016-01-05 下午4:26. */ public class Iterators { private static class MergingIterator<T> implements Iterator<T>{ final Queue<PeekingIterator<T>> queue; public MergingIterator(Iterable<? extends Iterator<? extends T>> iterators, final Comparator<? super T> itemComparator){ // A comparator that's used by the heap, allowing the heap // to be sorted based on the top of each iterator. Comparator<PeekingIterator<T>> heapComparator = new Comparator<PeekingIterator<T>>() { @Override public int compare(PeekingIterator<T> o1, PeekingIterator<T> o2) { return itemComparator.compare(o1.peek(), o2.peek()); } }; queue = new PriorityQueue<PeekingIterator<T>>(2, heapComparator); for (Iterator<? extends T> iterator : iterators) { if (iterator.hasNext()) { queue.add(Iterators.peekingIterator(iterator)); } } } public boolean hasNext() { return !queue.isEmpty(); } public T next() { PeekingIterator<T> nextIter = queue.remove(); T next = nextIter.next(); if (nextIter.hasNext()) { queue.add(nextIter); } return next; } @Override public void remove() { throw new UnsupportedOperationException(); } } public static <T> MergingIterator<T> mergeSorted(Iterable<? extends Iterator<? extends T>> iterators, Comparator<? super T> comparator) { checkNotNull(iterators); checkNotNull(comparator); return new MergingIterator<T>(iterators, comparator); } public static <T> PeekingIterator<T> peekingIterator(Iterator<? extends T> iterator) { if (iterator instanceof PeekingImpl) { // Safe to cast <? extends T> to <T> because PeekingImpl only uses T // covariantly (and cannot be subclassed to add non-covariant uses). @SuppressWarnings("unchecked") PeekingImpl<T> peeking = (PeekingImpl<T>) iterator; return peeking; } return new PeekingImpl<T>(iterator); } /** * Implementation of PeekingIterator that avoids peeking unless necessary. */ private static class PeekingImpl<E> implements PeekingIterator<E> { private final Iterator<? extends E> iterator; private boolean hasPeeked; private E peekedElement; public PeekingImpl(Iterator<? extends E> iterator){ this.iterator = checkNotNull(iterator); } @Override public boolean hasNext() { return hasPeeked || iterator.hasNext(); } @Override public E next() { if (!hasPeeked) { return iterator.next(); } E result = peekedElement; hasPeeked = false; peekedElement = null; return result; } @Override public void remove() { checkState(!hasPeeked, "Can't remove after you've peeked at next"); iterator.remove(); } @Override public E peek() { if (!hasPeeked) { peekedElement = iterator.next(); hasPeeked = true; } return peekedElement; } } /** * Ensures that an object reference passed as a parameter to the calling method is not null. * * @param reference an object reference * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static <T> T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } /** * Ensures the truth of an expression involving the state of the calling instance, but not * involving any parameters to the calling method. * * @param expression a boolean expression * @param errorMessage the exception message to use if the check fails; will be converted to a * string using {@link String#valueOf(Object)} * @throws IllegalStateException if {@code expression} is false */ public static void checkState(boolean expression, Object errorMessage) { if (!expression) { throw new IllegalStateException(String.valueOf(errorMessage)); } } }