Changeset 2465 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2009-11-16T18:51:28+01:00 (15 years ago)
Author:
jttt
Message:

Use String[] instead of HashMap for OsmPrimitive.keys - saves memory (15% for snapshot of Hungary)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java

    r2460 r2465  
    4141    }
    4242
     43    private static class KeysEntry implements Entry<String, String> {
     44
     45        private final String key;
     46        private final String value;
     47
     48        private KeysEntry(String key, String value) {
     49            this.key = key;
     50            this.value = value;
     51        }
     52
     53        public String getKey() {
     54            return key;
     55        }
     56
     57        public String getValue() {
     58            return value;
     59        }
     60
     61        public String setValue(String value) {
     62            throw new UnsupportedOperationException();
     63        }
     64
     65    }
     66
     67
    4368    private static final int FLAG_MODIFIED = 1 << 0;
    4469    private static final int FLAG_VISIBLE  = 1 << 1;
     
    539564     *
    540565     */
    541     private Map<String, String> keys;
     566    private Object keys;
     567    private static final String DEFAULT_KEY = "created_by";
    542568
    543569    /**
     
    549575     */
    550576    public Map<String, String> getKeys() {
    551         // TODO More effective map
    552         // fix for #3218
    553         if (keys == null)
    554             return new HashMap<String, String>();
    555         else
    556             return new HashMap<String, String>(keys);
     577        Map<String, String> result = new HashMap<String, String>();
     578        if (keys != null) {
     579            if (keys instanceof String) {
     580                result.put(DEFAULT_KEY, (String)keys);
     581            } else {
     582                String[] map = (String[])keys;
     583                if (map[0] != null) {
     584                    result.put(DEFAULT_KEY, map[0]);
     585                }
     586                for (int i=0; i<map.length / 2; i++) {
     587                    result.put(map[i * 2 + 1], map[i * 2 + 2]);
     588                }
     589            }
     590        }
     591        return result;
    557592    }
    558593
     
    568603            this.keys = null;
    569604        } else {
    570             this.keys = new HashMap<String, String>(keys);
     605            String[] newKeys = new String[keys.size() * 2 + (keys.containsKey(DEFAULT_KEY)?-1:1)];
     606            int index = 1;
     607            for (Entry<String, String> entry:keys.entrySet()) {
     608                if (DEFAULT_KEY.equals(entry.getKey())) {
     609                    newKeys[0] = entry.getValue();
     610                } else {
     611                    newKeys[index++] = entry.getKey();
     612                    newKeys[index++] = entry.getValue();
     613                }
     614            }
     615            this.keys = newKeys;
    571616        }
    572617        keysChangedImpl();
     
    588633            remove(key);
    589634        } else {
    590             if (keys == null) {
    591                 keys = new HashMap<String, String>();
    592             }
    593             keys.put(key, value);
    594         }
    595         keysChangedImpl();
     635            // TODO More effective implementation
     636            Map<String, String> keys = getKeys();
     637            if (!value.equals(keys.put(key, value))) {
     638                setKeys(keys);
     639                keysChangedImpl();
     640            }
     641        }
    596642    }
    597643    /**
     
    601647     */
    602648    public final void remove(String key) {
    603         if (keys != null) {
    604             keys.remove(key);
    605             if (keys.isEmpty()) {
    606                 keys = null;
    607             }
    608         }
    609         keysChangedImpl();
     649        Map<String, String> keys = getKeys();
     650        if (keys.remove(key) != null) {
     651            // TODO More effective implemenation
     652            setKeys(keys);
     653            keysChangedImpl();
     654        }
    610655    }
    611656
     
    628673     */
    629674    public final String get(String key) {
    630         if (key == null) return null;
    631         return keys == null ? null : keys.get(key);
     675        if (key == null)
     676            return null;
     677
     678        if (keys == null)
     679            return null;
     680
     681        if (keys instanceof String)
     682            return DEFAULT_KEY.equals(key)?(String)keys:null;
     683
     684            String[] map = (String[])keys;
     685            if (DEFAULT_KEY.equals(key))
     686                return map[0];
     687            else {
     688                for (int i=0; i<map.length/2; i++) {
     689                    if (key.equals(map[i * 2 + 1]))
     690                        return map[i * 2 + 2];
     691                }
     692            }
     693            return null;
    632694    }
    633695
    634696    public final Collection<Entry<String, String>> entrySet() {
    635697        if (keys == null)
    636             return Collections.emptyList();
    637         return keys.entrySet();
     698            return Collections.emptySet();
     699        else if (keys instanceof String)
     700            return Collections.<Entry<String, String>>singleton(new KeysEntry(DEFAULT_KEY, (String)keys));
     701        else {
     702            String[] map = (String[])keys;
     703            List<Entry<String, String>> result = new ArrayList<Entry<String,String>>();
     704            if (map[0] != null) {
     705                result.add(new KeysEntry(DEFAULT_KEY, map[0]));
     706            }
     707            for (int i=0; i<map.length / 2; i++) {
     708                result.add(new KeysEntry(map[i * 2 + 1], map[i * 2 + 2]));
     709            }
     710            return result;
     711        }
    638712    }
    639713
    640714    public final Collection<String> keySet() {
    641715        if (keys == null)
    642             return Collections.emptyList();
    643         return keys.keySet();
     716            return Collections.emptySet();
     717        else if (keys instanceof String)
     718            return Collections.singleton(DEFAULT_KEY);
     719        else {
     720            String[] map = (String[])keys;
     721            List<String> result = new ArrayList<String>(map.length / 2 + 1);
     722            if (map[0] != null) {
     723                result.add(DEFAULT_KEY);
     724            }
     725            for (int i=0; i<map.length / 2; i++) {
     726                result.add(map[i * 2 + 1]);
     727            }
     728            return result;
     729        }
     730    }
     731
     732    /**
     733     * Replies true, if the map of key/value pairs of this primitive is not empty.
     734     *
     735     * @return true, if the map of key/value pairs of this primitive is not empty; false
     736     *   otherwise
     737     */
     738    public final boolean hasKeys() {
     739        return keys != null;
     740    }
     741
     742    private void keysChangedImpl() {
     743        clearCached();
     744        updateHasDirectionKeys();
     745        updateTagged();
     746        if (dataSet != null) {
     747            dataSet.fireTagsChanged(this);
     748        }
    644749    }
    645750
     
    748853
    749854    /**
    750      * Replies true, if the map of key/value pairs of this primitive is not empty.
    751      *
    752      * @return true, if the map of key/value pairs of this primitive is not empty; false
    753      *   otherwise
    754      *
    755      * @since 1843
    756      */
    757     public final boolean hasKeys() {
    758         return keys != null && !keys.isEmpty();
    759     }
    760 
    761     private void keysChangedImpl() {
    762         clearCached();
    763         updateHasDirectionKeys();
    764         updateTagged();
    765         if (dataSet != null) {
    766             dataSet.fireTagsChanged(this);
    767         }
    768     }
    769 
    770     /**
    771855     * Get and write all attributes from the parameter. Does not fire any listener, so
    772856     * use this only in the data initializing phase
    773857     */
    774858    public void cloneFrom(OsmPrimitive osm) {
    775         keys = osm.keys == null ? null : new HashMap<String, String>(osm.keys);
     859        setKeys(osm.getKeys());
    776860        id = osm.id;
    777861        timestamp = osm.timestamp;
     
    801885        if (! other.isNew() && other.getId() != id)
    802886            throw new DataIntegrityProblemException(tr("Can''t merge primitives with different ids. This id is {0}, the other is {1}", id, other.getId()));
    803         keys = other.keys == null ? null : new HashMap<String, String>(other.keys);
     887        setKeys(other.getKeys());
    804888        timestamp = other.timestamp;
    805889        version = other.version;
     
    860944        getUninterestingKeys();
    861945        if (keys != null) {
    862             for (Entry<String,String> e : keys.entrySet()) {
     946            for (Entry<String,String> e : getKeys().entrySet()) {
    863947                if (!uninteresting.contains(e.getKey())) {
    864948                    flags |= FLAG_TAGGED;
     
    883967        getDirectionKeys();
    884968        if (keys != null) {
    885             for (Entry<String,String> e : keys.entrySet()) {
     969            for (Entry<String,String> e : getKeys().entrySet()) {
    886970                if (directionKeys.contains(e.getKey())) {
    887971                    flags |= FLAG_HAS_DIRECTIONS;
Note: See TracChangeset for help on using the changeset viewer.