Index: /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/actions/CreateMultipolygonAction.java	(revision 17585)
@@ -423,11 +423,11 @@
                 outerWays.add(way);
 
-                for (String key : way.keySet()) {
+                way.visitKeys((p, key, value) -> {
                     if (!values.containsKey(key)) { //relation values take precedence
-                        values.put(key, way.get(key));
-                    } else if (!values.get(key).equals(way.get(key))) {
+                        values.put(key, value);
+                    } else if (!values.get(key).equals(value)) {
                         conflictingKeys.add(key);
                     }
-                }
+                });
             }
         }
Index: /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 17585)
@@ -1698,7 +1698,5 @@
                 }
                 // Add tags
-                for (String key : r.rel.keySet()) {
-                    newRel.put(key, r.rel.get(key));
-                }
+                r.rel.visitKeys((p, key, value) -> newRel.put(key, value));
                 // Delete old relation
                 relationsToDelete.add(r.rel);
Index: /trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 17585)
@@ -6,4 +6,5 @@
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map;
 
 import javax.swing.JOptionPane;
@@ -60,6 +61,7 @@
     private static boolean checkMaxNodes(Collection<OsmPrimitive> primitives, long maxNodes) {
         for (OsmPrimitive osmPrimitive : primitives) {
-            for (String key: osmPrimitive.keySet()) {
-                String value = osmPrimitive.get(key);
+            for (Map.Entry<String, String> entry: osmPrimitive.getKeys().entrySet()) {
+                String key = entry.getKey();
+                String value = entry.getValue();
                 if (key.length() > Tagged.MAX_TAG_LENGTH) {
                     if (osmPrimitive.isDeleted()) {
Index: /trunk/src/org/openstreetmap/josm/data/osm/TagCollection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/TagCollection.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/data/osm/TagCollection.java	(revision 17585)
@@ -64,7 +64,5 @@
         TagCollection tags = new TagCollection();
         if (primitive != null) {
-            for (String key: primitive.keySet()) {
-                tags.add(new Tag(key, primitive.get(key)));
-            }
+            primitive.visitKeys((p, key, value) -> tags.add(new Tag(key, value)));
         }
         return tags;
Index: /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/data/osm/search/SearchCompiler.java	(revision 17585)
@@ -1063,6 +1063,7 @@
                 return search.isEmpty();
 
-            for (String key: osm.keySet()) {
-                String value = osm.get(key);
+            for (Map.Entry<String, String> entry: osm.getKeys().entrySet()) {
+                String key = entry.getKey();
+                String value = entry.getValue();
                 if (searchRegex != null) {
 
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/ConditionalKeys.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/ConditionalKeys.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/ConditionalKeys.java	(revision 17585)
@@ -18,5 +18,4 @@
 import org.openstreetmap.josm.data.validation.TestError;
 import org.openstreetmap.josm.tools.Logging;
-import org.openstreetmap.josm.tools.SubclassFilteredCollection;
 
 /**
@@ -224,6 +223,9 @@
     public List<TestError> validatePrimitive(OsmPrimitive p) {
         final List<TestError> errors = new ArrayList<>();
-        for (final String key : SubclassFilteredCollection.filter(p.keySet(),
-                Pattern.compile(":conditional(:.*)?$").asPredicate())) {
+        final Pattern pattern = Pattern.compile(":conditional(:.*)?$");
+        p.visitKeys((primitive, key, value) -> {
+            if (!pattern.matcher(key).find()) {
+                return;
+            }
             if (!isKeyValid(key)) {
                 errors.add(TestError.builder(this, Severity.WARNING, 3201)
@@ -231,7 +233,6 @@
                         .primitives(p)
                         .build());
-                continue;
-            }
-            final String value = p.get(key);
+                return;
+            }
             final String error = validateValue(key, value);
             if (error != null) {
@@ -241,5 +242,5 @@
                         .build());
             }
-        }
+        });
         return errors;
     }
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/InternetTags.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/InternetTags.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/InternetTags.java	(revision 17585)
@@ -122,5 +122,5 @@
     @Override
     public void check(OsmPrimitive p) {
-        for (String k : p.keySet()) {
+        p.visitKeys((primitive, k, value) -> {
             // Test key against URL validator
             if (!doTest(p, k, URL_KEYS, UrlValidator.getInstance(), INVALID_URL)) {
@@ -128,5 +128,5 @@
                 doTest(p, k, EMAIL_KEYS, EmailValidator.getInstance(), INVALID_EMAIL);
             }
-        }
+        });
     }
 }
Index: /trunk/src/org/openstreetmap/josm/gui/MapStatus.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/gui/MapStatus.java	(revision 17585)
@@ -643,7 +643,5 @@
             }
 
-            for (String key : osm.keySet()) {
-                text.append("<br>").append(key).append('=').append(osm.get(key));
-            }
+            osm.visitKeys((primitive, key, value) -> text.append("<br>").append(key).append('=').append(value));
 
             final JLabel l = new JLabel(
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDataText.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDataText.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/InspectPrimitiveDataText.java	(revision 17585)
@@ -164,8 +164,5 @@
         if (o.hasKeys()) {
             add(tr("Tags: "));
-            for (String key : o.keySet()) {
-                s.append(INDENT).append(INDENT);
-                s.append(String.format("\"%s\"=\"%s\"%n", key, o.get(key)));
-            }
+            o.visitKeys((primitive, key, value) -> s.append(INDENT).append(INDENT).append(String.format("\"%s\"=\"%s\"%n", key, value)));
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 17585)
@@ -659,7 +659,6 @@
         for (IPrimitive osm : newSel) {
             types.add(TaggingPresetType.forPrimitive(osm));
-            for (String key : osm.keySet()) {
+            osm.visitKeys((p, key, value) -> {
                 if (displayDiscardableKeys || !AbstractPrimitive.getDiscardableKeys().contains(key)) {
-                    String value = osm.get(key);
                     keyCount.put(key, keyCount.containsKey(key) ? keyCount.get(key) + 1 : 1);
                     if (valueCount.containsKey(key)) {
@@ -672,5 +671,5 @@
                     }
                 }
-            }
+            });
         }
         for (Entry<String, Map<String, Integer>> e : valueCount.entrySet()) {
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorModel.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/TagEditorModel.java	(revision 17585)
@@ -368,8 +368,5 @@
         commitPendingEdit();
         this.tags.clear();
-        for (String key : primitive.keySet()) {
-            String value = primitive.get(key);
-            this.tags.add(new TagModel(key, value));
-        }
+        primitive.visitKeys((p, key, value) -> this.tags.add(new TagModel(key, value)));
         sort();
         TagModel tag = new TagModel();
@@ -512,9 +509,9 @@
 
         for (OsmPrimitive prim : primitives) {
-            for (String oldkey : prim.keySet()) {
+            prim.visitKeys((p, oldkey, value) -> {
                 if (!currentkeys.contains(oldkey)) {
                     commands.add(new ChangePropertyCommand(prim, oldkey, null));
                 }
-            }
+            });
         }
 
Index: /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java	(revision 17584)
+++ /trunk/src/org/openstreetmap/josm/gui/tagging/ac/AutoCompletionManager.java	(revision 17585)
@@ -193,8 +193,5 @@
      */
     protected void cachePrimitiveTags(OsmPrimitive primitive) {
-        for (String key: primitive.keySet()) {
-            String value = primitive.get(key);
-            tagCache.put(key, value);
-        }
+        primitive.visitKeys((p, key, value) -> tagCache.put(key, value));
     }
 
