Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21ab6f49 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

ArrayMap is great, so how about ArraySet!

Also a few little tweaks to the ArrayMap implementation.  Note that
these are fairly parallel implementations; I looked at what I could
abstract out as a base class, but there isn't really all that much without
making the resulting code more general and thus slower.  If we kept
the data structure for ArraySet the same as map, where the array has
two values per entry, then they could probably share a lot of code.
I couldn't really bring myself to do that at this point, though...

Change-Id: I9e0dd8baa8e1febcc1033ecef61623ad59ce4aae
parent be4e6aaa
Loading
Loading
Loading
Loading
+60 −63
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ public final class ArrayMap<K, V> implements Map<K, V> {
        }
        mSize = 0;
    }

    /**
     * Create a new ArrayMap with the mappings from the given ArrayMap.
     */
@@ -216,7 +217,6 @@ public final class ArrayMap<K, V> implements Map<K, V> {
        }
    }


    /**
     * Make the array map empty.  All storage is released.
     */
@@ -236,8 +236,8 @@ public final class ArrayMap<K, V> implements Map<K, V> {
     */
    public void ensureCapacity(int minimumCapacity) {
        if (mHashes.length < minimumCapacity) {
            int[] ohashes = mHashes;
            Object[] oarray = mArray;
            final int[] ohashes = mHashes;
            final Object[] oarray = mArray;
            allocArrays(minimumCapacity);
            if (mSize > 0) {
                System.arraycopy(ohashes, 0, mHashes, 0, mSize);
@@ -493,6 +493,63 @@ public final class ArrayMap<K, V> implements Map<K, V> {
        return mSize;
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation returns false if the object is not a map, or
     * if the maps have different sizes. Otherwise, for each key in this map,
     * values of both maps are compared. If the values for any key are not
     * equal, the method returns false, otherwise it returns true.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) object;
            if (size() != map.size()) {
                return false;
            }

            try {
                for (int i=0; i<mSize; i++) {
                    K key = keyAt(i);
                    V mine = valueAt(i);
                    Object theirs = map.get(key);
                    if (mine == null) {
                        if (theirs != null || !map.containsKey(key)) {
                            return false;
                        }
                    } else if (!mine.equals(theirs)) {
                        return false;
                    }
                }
            } catch (NullPointerException ignored) {
                return false;
            } catch (ClassCastException ignored) {
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        final int[] hashes = mHashes;
        final Object[] array = mArray;
        int result = 0;
        for (int i = 0, v = 1, s = mSize; i < s; i++, v+=2) {
            Object value = array[v];
            result += hashes[i] ^ (value == null ? 0 : value.hashCode());
        }
        return result;
    }

    // ------------------------------------------------------------------------
    // Interop with traditional Java containers.  Not as efficient as using
    // specialized collection APIs.
@@ -632,64 +689,4 @@ public final class ArrayMap<K, V> implements Map<K, V> {
    public Collection<V> values() {
        return getCollection().getValues();
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation returns false if the object is not a map, or
     * if the maps have different sizes. Otherwise, for each key in this map,
     * values of both maps are compared. If the values for any key are not
     * equal, the method returns false, otherwise it returns true.
     */
    @Override
    public boolean equals(Object object) {
        if (this == object) {
            return true;
        }
        if (object instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) object;
            if (size() != map.size()) {
                return false;
            }

            try {
                for (int i=0; i<mSize; i++) {
                    K key = keyAt(i);
                    V mine = valueAt(i);
                    Object theirs = map.get(key);
                    if (mine == null) {
                        if (theirs != null || !map.containsKey(key)) {
                            return false;
                        }
                    } else if (!mine.equals(theirs)) {
                        return false;
                    }
                }
            } catch (NullPointerException ignored) {
                return false;
            } catch (ClassCastException ignored) {
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * {@inheritDoc}
     *
     * <p>This implementation sums a hashcode using all keys and values.
     */
    @Override
    public int hashCode() {
        int result = 0;
        for (int i=0; i<mSize; i++) {
            K key = keyAt(i);
            V value = valueAt(i);
            result += (key == null ? 0 : key.hashCode())
                    ^ (value == null ? 0 : value.hashCode());
        }
        return result;
    }

}
+599 −0

File added.

Preview size limit exceeded, changes collapsed.

+150 −56

File changed.

Preview size limit exceeded, changes collapsed.