Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 3206)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 3207)
@@ -28,4 +28,5 @@
 import org.openstreetmap.josm.data.osm.event.TagsChangedEvent;
 import org.openstreetmap.josm.data.osm.event.WayNodesChangedEvent;
+import org.openstreetmap.josm.tools.Predicate;
 
 /**
@@ -52,5 +53,5 @@
     }
 
-    private Storage<OsmPrimitive> allPrimitives = new Storage<OsmPrimitive>(new IdHash());
+    private Storage<OsmPrimitive> allPrimitives = new Storage<OsmPrimitive>(new IdHash(), 16, true);
     private Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new IdHash());
     private List<DataSetListener> listeners = new ArrayList<DataSetListener>();
@@ -98,4 +99,8 @@
     private QuadBuckets<Node> nodes = new QuadBuckets<Node>();
 
+    private <T extends OsmPrimitive> Collection<T> getPrimitives(Predicate<OsmPrimitive> predicate) {
+        return new DatasetCollection<T>(allPrimitives, predicate);
+    }
+
     /**
      * Replies an unmodifiable collection of nodes in this dataset
@@ -104,5 +109,5 @@
      */
     public Collection<Node> getNodes() {
-        return Collections.unmodifiableCollection(nodes);
+        return getPrimitives(OsmPrimitive.nodePredicate);
     }
 
@@ -124,5 +129,5 @@
      */
     public Collection<Way> getWays() {
-        return Collections.unmodifiableCollection(ways);
+        return getPrimitives(OsmPrimitive.wayPredicate);
     }
 
@@ -134,5 +139,5 @@
      * All relations/relationships
      */
-    private Collection<Relation> relations = new LinkedList<Relation>();
+    private Collection<Relation> relations = new ArrayList<Relation>();
 
     /**
@@ -142,5 +147,5 @@
      */
     public Collection<Relation> getRelations() {
-        return Collections.unmodifiableCollection(relations);
+        return getPrimitives(OsmPrimitive.relationPredicate);
     }
 
@@ -165,5 +170,5 @@
      */
     public Collection<OsmPrimitive> allPrimitives() {
-        return Collections.unmodifiableCollection(allPrimitives);
+        return getPrimitives(OsmPrimitive.allPredicate);
     }
 
@@ -172,17 +177,17 @@
      */
     public Collection<OsmPrimitive> allNonDeletedPrimitives() {
-        return new DatasetCollection(allPrimitives, OsmPrimitive.nonDeletedPredicate);
+        return getPrimitives(OsmPrimitive.nonDeletedPredicate);
     }
 
     public Collection<OsmPrimitive> allNonDeletedCompletePrimitives() {
-        return new DatasetCollection(allPrimitives, OsmPrimitive.nonDeletedCompletePredicate);
+        return getPrimitives(OsmPrimitive.nonDeletedCompletePredicate);
     }
 
     public Collection<OsmPrimitive> allNonDeletedPhysicalPrimitives() {
-        return new DatasetCollection(allPrimitives, OsmPrimitive.nonDeletedPhysicalPredicate);
+        return getPrimitives(OsmPrimitive.nonDeletedPhysicalPredicate);
     }
 
     public Collection<OsmPrimitive> allModifiedPrimitives() {
-        return new DatasetCollection(allPrimitives, OsmPrimitive.modifiedPredicate);
+        return getPrimitives(OsmPrimitive.modifiedPredicate);
     }
 
@@ -471,12 +476,30 @@
             return;
         }
+        clearDisabled(allPrimitives());
+        for (OsmPrimitive o : osm)
+            if (o != null) {
+                o.setDisabled(true);
+            }
+    }
+
+    public void setDisabled(Collection<? extends OsmPrimitive> selection) {
         clearDisabled(nodes);
         clearDisabled(ways);
         clearDisabled(relations);
-        for (OsmPrimitive o : osm)
-            if (o != null) {
-                o.setDisabled(true);
-            }
-    }
+        for (OsmPrimitive osm : selection) {
+            osm.setDisabled(true);
+        }
+    }
+
+    /**
+     * Remove the disabled parameter from every value in the collection.
+     * @param list The collection to remove the disabled parameter from.
+     */
+    private void clearDisabled(Collection<? extends OsmPrimitive> list) {
+        for (OsmPrimitive osm : list) {
+            osm.setDisabled(false);
+        }
+    }
+
 
     public void setFiltered(Collection<? extends OsmPrimitive> selection) {
@@ -503,13 +526,4 @@
     }
 
-    public void setDisabled(Collection<? extends OsmPrimitive> selection) {
-        clearDisabled(nodes);
-        clearDisabled(ways);
-        clearDisabled(relations);
-        for (OsmPrimitive osm : selection) {
-            osm.setDisabled(true);
-        }
-    }
-
     /**
      * Remove the filtered parameter from every value in the collection.
@@ -521,15 +535,4 @@
         for (OsmPrimitive osm : list) {
             osm.setFiltered(false);
-        }
-    }
-    /**
-     * Remove the disabled parameter from every value in the collection.
-     * @param list The collection to remove the disabled parameter from.
-     */
-    private void clearDisabled(Collection<? extends OsmPrimitive> list) {
-        if (list == null)
-            return;
-        for (OsmPrimitive osm : list) {
-            osm.setDisabled(false);
         }
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/DatasetCollection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DatasetCollection.java	(revision 3206)
+++ trunk/src/org/openstreetmap/josm/data/osm/DatasetCollection.java	(revision 3207)
@@ -8,7 +8,7 @@
 import org.openstreetmap.josm.tools.Predicate;
 
-public class DatasetCollection extends AbstractCollection<OsmPrimitive> {
+public class DatasetCollection<T extends OsmPrimitive> extends AbstractCollection<T> {
 
-    private class FilterIterator implements Iterator<OsmPrimitive> {
+    private class FilterIterator implements Iterator<T> {
 
         private final Iterator<? extends OsmPrimitive> iterator;
@@ -35,9 +35,10 @@
         }
 
-        public OsmPrimitive next() {
+        @SuppressWarnings("unchecked")
+        public T next() {
             findNext();
             OsmPrimitive old = current;
             current = null;
-            return old;
+            return (T)old;
         }
 
@@ -56,5 +57,5 @@
 
     @Override
-    public Iterator<OsmPrimitive> iterator() {
+    public Iterator<T> iterator() {
         return new FilterIterator(primitives.iterator());
     }
@@ -63,5 +64,5 @@
     public int size() {
         int size = 0;
-        Iterator<OsmPrimitive> it = iterator();
+        Iterator<T> it = iterator();
         while (it.hasNext()) {
             size++;
Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 3206)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 3207)
@@ -438,4 +438,29 @@
         }
     };
+
+    public static Predicate<OsmPrimitive> nodePredicate = new Predicate<OsmPrimitive>() {
+        public boolean evaluate(OsmPrimitive primitive) {
+            return primitive.getClass() == Node.class;
+        }
+    };
+
+    public static Predicate<OsmPrimitive> wayPredicate = new Predicate<OsmPrimitive>() {
+        public boolean evaluate(OsmPrimitive primitive) {
+            return primitive.getClass() == Way.class;
+        }
+    };
+
+    public static Predicate<OsmPrimitive> relationPredicate = new Predicate<OsmPrimitive>() {
+        public boolean evaluate(OsmPrimitive primitive) {
+            return primitive.getClass() == Relation.class;
+        }
+    };
+
+    public static Predicate<OsmPrimitive> allPredicate = new Predicate<OsmPrimitive>() {
+        public boolean evaluate(OsmPrimitive primitive) {
+            return true;
+        }
+    };
+
 
     /**
Index: trunk/src/org/openstreetmap/josm/data/osm/Storage.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Storage.java	(revision 3206)
+++ trunk/src/org/openstreetmap/josm/data/osm/Storage.java	(revision 3207)
@@ -23,4 +23,5 @@
 import java.util.AbstractSet;
 import java.util.Collection;
+import java.util.ConcurrentModificationException;
 import java.util.Iterator;
 import java.util.Map;
@@ -92,4 +93,6 @@
     private transient volatile int modCount = 0;
     private float loadFactor = 0.6f;
+    private final boolean safeIterator;
+    private boolean arrayCopyNecessary;
 
     public Storage() {
@@ -98,45 +101,61 @@
 
     public Storage(int capacity) {
-        this(Storage.<T>defaultHash(), capacity);
+        this(Storage.<T>defaultHash(), capacity, false);
     }
 
     public Storage(Hash<? super T,? super T> ha) {
-        this(ha, 16);
-    }
-
-    public Storage(Hash<? super T, ? super T> ha, int capacity) {
+        this(ha, 16, false);
+    }
+
+    public Storage(Hash<? super T, ? super T> ha, int capacity, boolean safeIterator) {
         this.hash = ha;
         int cap = 1 << (int)(Math.ceil(Math.log(capacity/loadFactor) / Math.log(2)));
         data = new Object[cap];
         mask = data.length - 1;
+        this.safeIterator = safeIterator;
+    }
+
+    private void copyArray() {
+        if (arrayCopyNecessary) {
+            Object[] newData = new Object[data.length];
+            System.arraycopy(data, 0, newData, 0, data.length);
+            data = newData;
+            arrayCopyNecessary = false;
+        }
     }
 
     // --------------- Collection implementation ------------------------
     @Override
-    public int size() {
+    public synchronized int size() {
         return size;
     }
 
     @Override
-    public Iterator<T> iterator() {
-        return new Iter();
-    }
-
-    public @Override boolean contains(Object o) {
+    public synchronized Iterator<T> iterator() {
+        if (safeIterator) {
+            arrayCopyNecessary = true;
+            return new SafeReadonlyIter(data);
+        } else
+            return new Iter();
+
+    }
+
+    public synchronized @Override boolean contains(Object o) {
         int bucket = getBucket(hash, (T)o);
         return bucket >= 0;
     }
 
-    public @Override boolean add(T t) {
+    public synchronized @Override boolean add(T t) {
         T orig = putUnique(t);
         return orig == t;
     }
 
-    public @Override boolean remove(Object o) {
+    public synchronized @Override boolean remove(Object o) {
         T orig = removeElem((T)o);
         return orig != null;
     }
 
-    public @Override void clear() {
+    public synchronized @Override void clear() {
+        copyArray();
         modCount++;
         size = 0;
@@ -146,5 +165,5 @@
     }
 
-    public @Override int hashCode() {
+    public synchronized @Override int hashCode() {
         int h = 0;
         for (T t : this) {
@@ -156,5 +175,6 @@
     // ----------------- Extended API ----------------------------
 
-    public T put(T t) {
+    public synchronized T put(T t) {
+        copyArray();
         modCount++;
         ensureSpace();
@@ -173,10 +193,11 @@
     }
 
-    public T get(T t) {
+    public synchronized T get(T t) {
         int bucket = getBucket(hash, t);
         return bucket < 0 ? null : (T)data[bucket];
     }
 
-    public T putUnique(T t) {
+    public synchronized T putUnique(T t) {
+        copyArray();
         modCount++;
         ensureSpace();
@@ -193,5 +214,6 @@
     }
 
-    public T removeElem(T t) {
+    public synchronized T removeElem(T t) {
+        copyArray();
         modCount++;
         int bucket = getBucket(hash, t);
@@ -381,4 +403,34 @@
     }
 
+    private final class SafeReadonlyIter implements Iterator<T> {
+        final Object[] data;
+        int slot = 0;
+
+        SafeReadonlyIter(Object[] data) {
+            this.data = data;
+        }
+
+        public boolean hasNext() {
+            align();
+            return slot < data.length;
+        }
+
+        public T next() {
+            if (!hasNext()) throw new NoSuchElementException();
+            return (T)data[slot++];
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        private void align() {
+            while (slot < data.length && data[slot] == null) {
+                slot++;
+            }
+        }
+    }
+
+
     private final class Iter implements Iterator<T> {
         private final int mods;
@@ -410,9 +462,6 @@
 
         private void align() {
-            if (mods != modCount) {
-                System.err.println("Warning: ConcurrentModification");
-                Thread.dumpStack();
-                //throw new ConcurrentModificationException();
-            }
+            if (mods != modCount)
+                throw new ConcurrentModificationException();
             while (slot < data.length && data[slot] == null) {
                 slot++;
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 3206)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 3207)
@@ -270,6 +270,6 @@
 
     @Override public String getToolTipText() {
-        int nodes = new DatasetCollection(data.getNodes(), OsmPrimitive.nonDeletedPredicate).size();
-        int ways = new DatasetCollection(data.getWays(), OsmPrimitive.nonDeletedPredicate).size();
+        int nodes = new DatasetCollection<OsmPrimitive>(data.getNodes(), OsmPrimitive.nonDeletedPredicate).size();
+        int ways = new DatasetCollection<OsmPrimitive>(data.getWays(), OsmPrimitive.nonDeletedPredicate).size();
 
         String tool = trn("{0} node", "{0} nodes", nodes, nodes)+", ";
