// Path: collection/src/main/java/com/github/andrewoma/dexx/collection/KeyFunction.java
// public interface KeyFunction<K, V> {
//     @NotNull
//     K key(@NotNull V value);
// }
// 
// Path: collection/src/main/java/com/github/andrewoma/dexx/collection/Pair.java
// public class Pair<C1, C2> {
//     private final C1 component1;
//     private final C2 component2;
// 
//     public Pair(C1 component1, C2 component2) {
//         this.component1 = component1;
//         this.component2 = component2;
//     }
// 
//     public C1 component1() {
//         return component1;
//     }
// 
//     public C2 component2() {
//         return component2;
//     }
// 
//     @Override
//     public String toString() {
//         return "(" + component1 + ", " + component2 + ")";
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Pair pair = (Pair) o;
//         return !(component1 != null ? !component1.equals(pair.component1) : pair.component1 != null)
//                 && !(component2 != null ? !component2.equals(pair.component2) : pair.component2 != null);
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = component1 != null ? component1.hashCode() : 0;
//         result = 31 * result + (component2 != null ? component2.hashCode() : 0);
//         return result;
//     }
// }


import com.github.andrewoma.dexx.collection.KeyFunction;
import com.github.andrewoma.dexx.collection.Pair;
import java.util.Iterator;
import java.util.NoSuchElementException;
        try {
            path[index] = tree;
            index += 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            /*
            * Either the tree became unbalanced or we calculated the maximum height incorrectly.
            * To avoid crashing the iterator we expand the path array. Obviously this should never
            * happen...
            *
            * An exception handler is used instead of an if-condition to optimize the normal path.
            * This makes a large difference in iteration speed!
            */
            e.printStackTrace();
            assert (index >= path.length);
            Tree<K, V>[] temp = new Tree[path.length + 1];
            System.arraycopy(path, 0, temp, 0, path.length);
            path = temp;
            pushPath(tree);
        }
    }

    private Tree<K, V> popPath() {
        if (index == 0)
            return null;

        index -= 1;
        return path[index];
    }
}

// Path: collection/src/main/java/com/github/andrewoma/dexx/collection/KeyFunction.java
// public interface KeyFunction<K, V> {
//     @NotNull
//     K key(@NotNull V value);
// }
// 
// Path: collection/src/main/java/com/github/andrewoma/dexx/collection/Pair.java
// public class Pair<C1, C2> {
//     private final C1 component1;
//     private final C2 component2;
// 
//     public Pair(C1 component1, C2 component2) {
//         this.component1 = component1;
//         this.component2 = component2;
//     }
// 
//     public C1 component1() {
//         return component1;
//     }
// 
//     public C2 component2() {
//         return component2;
//     }
// 
//     @Override
//     public String toString() {
//         return "(" + component1 + ", " + component2 + ")";
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Pair pair = (Pair) o;
//         return !(component1 != null ? !component1.equals(pair.component1) : pair.component1 != null)
//                 && !(component2 != null ? !component2.equals(pair.component2) : pair.component2 != null);
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = component1 != null ? component1.hashCode() : 0;
//         result = 31 * result + (component2 != null ? component2.hashCode() : 0);
//         return result;
//     }
// }


// Path: collection/src/main/java/com/github/andrewoma/dexx/collection/internal/redblack/TreeIterator.java
import com.github.andrewoma.dexx.collection.KeyFunction;
import com.github.andrewoma.dexx.collection.Pair;
import java.util.Iterator;
import java.util.NoSuchElementException;

        try {
            path[index] = tree;
            index += 1;
        } catch (ArrayIndexOutOfBoundsException e) {
            /*
            * Either the tree became unbalanced or we calculated the maximum height incorrectly.
            * To avoid crashing the iterator we expand the path array. Obviously this should never
            * happen...
            *
            * An exception handler is used instead of an if-condition to optimize the normal path.
            * This makes a large difference in iteration speed!
            */
            e.printStackTrace();
            assert (index >= path.length);
            Tree<K, V>[] temp = new Tree[path.length + 1];
            System.arraycopy(path, 0, temp, 0, path.length);
            path = temp;
            pushPath(tree);
        }
    }

    private Tree<K, V> popPath() {
        if (index == 0)
            return null;

        index -= 1;
        return path[index];
    }
}

class EntriesIterator<K, V> extends TreeIterator<K, V, Pair<K, V>> {