diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java index c2c9cac2cc..ec71780ca3 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java @@ -81,6 +81,7 @@ public class VectorTile { // TODO make these configurable private static final int EXTENT = 4096; private static final double SIZE = 256d; + // use a treemap to ensure that layers are encoded in a consistent order private final Map layers = new TreeMap<>(); private LayerAttrStats.Updater.ForZoom layerStatsTracker = LayerAttrStats.Updater.ForZoom.NOOP; diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/LongMerger.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/LongMerger.java index 9a8951c7f9..b7d72759e9 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/LongMerger.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/collection/LongMerger.java @@ -34,10 +34,6 @@ public static Iterator mergeIterators(List boolean lessThan(long ak, long bk, T a, T b, Comparator tieBreaker) { - return ak < bk || (ak == bk && a != null && b != null && tieBreaker.compare(a, b) < 0); - } - private static class TwoWayMerge implements Iterator { private final Comparator tieBreaker; @@ -67,7 +63,7 @@ public boolean hasNext() { @Override public T next() { T result; - if (lessThan(ak, bk, a, b, tieBreaker)) { + if (lessThan(ak, bk, a, b)) { result = a; if (inputA.hasNext()) { a = inputA.next(); @@ -90,6 +86,10 @@ public T next() { } return result; } + + private boolean lessThan(long ak, long bk, T a, T b) { + return ak < bk || (ak == bk && a != null && b != null && tieBreaker.compare(a, b) < 0); + } } private static class ThreeWayMerge implements Iterator { @@ -127,8 +127,8 @@ public boolean hasNext() { public T next() { T result; // use at most 2 comparisons to get the next item - if (lessThan(ak, bk, a, b, tieBreaker)) { - if (lessThan(ak, ck, a, c, tieBreaker)) { + if (lessThan(ak, bk, a, b)) { + if (lessThan(ak, ck, a, c)) { // ACB / ABC result = a; if (inputA.hasNext()) { @@ -149,7 +149,7 @@ public T next() { ck = Long.MAX_VALUE; } } - } else if (lessThan(ck, bk, c, b, tieBreaker)) { /* (ck < bk) {*/ + } else if (lessThan(ck, bk, c, b)) { // CAB result = c; if (inputC.hasNext()) { @@ -174,6 +174,21 @@ public T next() { } return result; } + + private boolean lessThan(long ak, long bk, T a, T b) { + return ak < bk || (ak == bk && lessThanCmp(a, b, tieBreaker)); + } + } + + private static boolean lessThanCmp(T a, T b, Comparator tieBreaker) { + // nulls go at the end + if (a == null) { + return false; + } else if (b == null) { + return true; + } else { + return tieBreaker.compare(a, b) < 0; + } } private static class KWayMerge implements Iterator { @@ -185,10 +200,7 @@ private static class KWayMerge implements Iterator KWayMerge(List> inputIterators, Comparator tieBreaker) { this.iterators = new Iterator[inputIterators.size()]; this.items = (T[]) new HasLongSortKey[inputIterators.size()]; - final int size = inputIterators.size(); - this.heap = LongMinHeap.newArrayHeap(inputIterators.size(), (a, b) -> { - return a >= size || b >= size ? 0 : tieBreaker.compare(items[a], items[b]); - }); + this.heap = LongMinHeap.newArrayHeap(inputIterators.size(), (a, b) -> tieBreaker.compare(items[a], items[b])); int outIdx = 0; for (Iterator iter : inputIterators) { if (iter.hasNext()) {