Index: /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/MVTTile.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/MVTTile.java	(revision 18477)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/MVTTile.java	(revision 18478)
@@ -5,6 +5,6 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -53,5 +53,5 @@
             ProtobufParser parser = new ProtobufParser(inputStream);
             Collection<ProtobufRecord> protobufRecords = parser.allRecords();
-            this.layers = new HashSet<>(protobufRecords.size());
+            this.layers = new ArrayList<>(protobufRecords.size());
             for (ProtobufRecord protoBufRecord : protobufRecords) {
                 if (protoBufRecord.getField() == Layer.LAYER_FIELD) {
@@ -66,5 +66,5 @@
                 }
             }
-            this.layers = new HashSet<>(this.layers);
+            this.layers = new ArrayList<>(this.layers);
 
             this.extent = layers.stream().filter(Objects::nonNull).mapToInt(Layer::getExtent).max().orElse(Layer.DEFAULT_EXTENT);
Index: /trunk/src/org/openstreetmap/josm/data/vector/VectorDataStore.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/vector/VectorDataStore.java	(revision 18477)
+++ /trunk/src/org/openstreetmap/josm/data/vector/VectorDataStore.java	(revision 18478)
@@ -13,5 +13,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -22,5 +21,4 @@
 import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
 import org.openstreetmap.josm.data.IQuadBucketType;
-import org.openstreetmap.josm.data.coor.ILatLon;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.imagery.vectortile.VectorTile;
@@ -163,5 +161,5 @@
 
     private synchronized <T extends Tile & VectorTile> VectorNode pointToNode(T tile, Layer layer,
-      Collection<VectorPrimitive> featureObjects, int x, int y, final Map<ILatLon, VectorNode> nodeMap) {
+      Collection<VectorPrimitive> featureObjects, int x, int y) {
         final BBox tileBbox;
         if (tile instanceof IQuadBucketType) {
@@ -179,7 +177,4 @@
                 tileBbox.getMinLon() + (tileBbox.getMaxLon() - tileBbox.getMinLon()) * x / layerExtent
         );
-        if (nodeMap.containsKey(coords)) {
-            return nodeMap.get(coords);
-        }
         final Collection<VectorNode> nodes = this.store
           .searchNodes(new BBox(coords.lon(), coords.lat(), VectorDataSet.DUPE_NODE_DISTANCE));
@@ -212,13 +207,12 @@
         node.setCoor(coords);
         featureObjects.add(node);
-        nodeMap.put(node.getCoor(), node);
         return node;
     }
 
     private <T extends Tile & VectorTile> List<VectorWay> pathToWay(T tile, Layer layer,
-      Collection<VectorPrimitive> featureObjects, Path2D shape, Map<ILatLon, VectorNode> nodeMap) {
+      Collection<VectorPrimitive> featureObjects, Path2D shape) {
         final PathIterator pathIterator = shape.getPathIterator(null);
         final List<VectorWay> ways = new ArrayList<>(
-                Utils.filteredCollection(pathIteratorToObjects(tile, layer, featureObjects, pathIterator, nodeMap), VectorWay.class));
+                Utils.filteredCollection(pathIteratorToObjects(tile, layer, featureObjects, pathIterator), VectorWay.class));
         // These nodes technically do not exist, so we shouldn't show them
         for (VectorWay way : ways) {
@@ -234,5 +228,5 @@
 
     private <T extends Tile & VectorTile> List<VectorPrimitive> pathIteratorToObjects(T tile, Layer layer,
-      Collection<VectorPrimitive> featureObjects, PathIterator pathIterator, Map<ILatLon, VectorNode> nodeMap) {
+      Collection<VectorPrimitive> featureObjects, PathIterator pathIterator) {
         final List<VectorNode> nodes = new ArrayList<>();
         final double[] coords = new double[6];
@@ -255,5 +249,5 @@
             }
             if (PathIterator.SEG_MOVETO == type || PathIterator.SEG_LINETO == type) {
-                final VectorNode node = pointToNode(tile, layer, featureObjects, (int) coords[0], (int) coords[1], nodeMap);
+                final VectorNode node = pointToNode(tile, layer, featureObjects, (int) coords[0], (int) coords[1]);
                 nodes.add(node);
             } else if (PathIterator.SEG_CLOSE != type) {
@@ -272,7 +266,7 @@
 
     private <T extends Tile & VectorTile> VectorRelation areaToRelation(T tile, Layer layer,
-      Collection<VectorPrimitive> featureObjects, Area area, Map<ILatLon, VectorNode> nodeMap) {
+      Collection<VectorPrimitive> featureObjects, Area area) {
         VectorRelation vectorRelation = new VectorRelation(layer.getName());
-        for (VectorPrimitive member : pathIteratorToObjects(tile, layer, featureObjects, area.getPathIterator(null), nodeMap)) {
+        for (VectorPrimitive member : pathIteratorToObjects(tile, layer, featureObjects, area.getPathIterator(null))) {
             final String role;
             if (member instanceof VectorWay && ((VectorWay) member).isClosed()) {
@@ -294,5 +288,4 @@
         // Using a map reduces the cost of addFeatureData from 2,715,158,632 bytes to 235,042,184 bytes (-91.3%)
         // This was somewhat variant, with some runs being closer to ~560 MB (still -80%).
-        final Map<ILatLon, VectorNode> nodeMap = new HashMap<>();
         for (Layer layer : tile.getLayers()) {
             Map<GeometryTypes, List<Feature>> grouped = layer.getFeatures().stream().collect(Collectors.groupingBy(Feature::getGeometryType));
@@ -300,5 +293,5 @@
             for (GeometryTypes type : GeometryTypes.values()) {
                 if (grouped.containsKey(type)) {
-                    addFeatureData(tile, layer, grouped.get(type), nodeMap);
+                    addFeatureData(tile, layer, grouped.get(type));
                 }
             }
@@ -313,8 +306,8 @@
     }
 
-    private <T extends Tile & VectorTile> void addFeatureData(T tile, Layer layer, Collection<Feature> features, Map<ILatLon, VectorNode> nodeMap) {
+    private <T extends Tile & VectorTile> void addFeatureData(T tile, Layer layer, Collection<Feature> features) {
         for (Feature feature : features) {
             try {
-                addFeatureData(tile, layer, feature, nodeMap);
+                addFeatureData(tile, layer, feature);
             } catch (IllegalArgumentException e) {
                 Logging.error("Cannot add vector data for feature {0} of tile {1}: {2}", feature, tile, e.getMessage());
@@ -324,10 +317,10 @@
     }
 
-    private <T extends Tile & VectorTile> void addFeatureData(T tile, Layer layer, Feature feature, Map<ILatLon, VectorNode> nodeMap) {
+    private <T extends Tile & VectorTile> void addFeatureData(T tile, Layer layer, Feature feature) {
         // This will typically be larger than primaryFeatureObjects, but this at least avoids quite a few ArrayList#grow calls
         List<VectorPrimitive> featureObjects = new ArrayList<>(feature.getGeometryObject().getShapes().size());
         List<VectorPrimitive> primaryFeatureObjects = new ArrayList<>(feature.getGeometryObject().getShapes().size());
         for (Shape shape : feature.getGeometryObject().getShapes()) {
-            primaryFeatureObjects.add(shapeToPrimaryFeatureObject(tile, layer, shape, featureObjects, nodeMap));
+            primaryFeatureObjects.add(shapeToPrimaryFeatureObject(tile, layer, shape, featureObjects));
         }
         final VectorPrimitive primitive;
@@ -374,13 +367,13 @@
 
     private <T extends Tile & VectorTile> VectorPrimitive shapeToPrimaryFeatureObject(
-            T tile, Layer layer, Shape shape, List<VectorPrimitive> featureObjects, Map<ILatLon, VectorNode> nodeMap) {
+            T tile, Layer layer, Shape shape, List<VectorPrimitive> featureObjects) {
         final VectorPrimitive primitive;
         if (shape instanceof Ellipse2D) {
             primitive = pointToNode(tile, layer, featureObjects,
-                    (int) ((Ellipse2D) shape).getCenterX(), (int) ((Ellipse2D) shape).getCenterY(), nodeMap);
+                    (int) ((Ellipse2D) shape).getCenterX(), (int) ((Ellipse2D) shape).getCenterY());
         } else if (shape instanceof Path2D) {
-            primitive = pathToWay(tile, layer, featureObjects, (Path2D) shape, nodeMap).stream().findFirst().orElse(null);
+            primitive = pathToWay(tile, layer, featureObjects, (Path2D) shape).stream().findFirst().orElse(null);
         } else if (shape instanceof Area) {
-            primitive = areaToRelation(tile, layer, featureObjects, (Area) shape, nodeMap);
+            primitive = areaToRelation(tile, layer, featureObjects, (Area) shape);
             primitive.put(RELATION_TYPE, MULTIPOLYGON_TYPE);
         } else {
Index: /trunk/test/unit/org/openstreetmap/josm/data/vector/VectorDataSetTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/vector/VectorDataSetTest.java	(revision 18477)
+++ /trunk/test/unit/org/openstreetmap/josm/data/vector/VectorDataSetTest.java	(revision 18478)
@@ -14,5 +14,5 @@
 import org.awaitility.Durations;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.RepeatedTest;
 import org.junit.jupiter.api.extension.RegisterExtension;
 import org.openstreetmap.josm.TestUtils;
@@ -99,5 +99,9 @@
     }
 
-    @Test
+    /**
+     * This failed about 1/2 times.
+     * It tests for node deduplication.
+     */
+    @RepeatedTest(10)
     void testNodeDeduplication() {
         final VectorDataSet dataSet = this.layer.getData();
