Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ArrayList.contains() vs HashMap.containsKey() vs HashMap.get()

Does ArrayList.contains() have to iterate over all items to do its check? Does HashMap.containsKey()? I know HashMap.get() doesn't need to, but is that why it is the most efficient?

like image 727
Adam Johns Avatar asked Oct 26 '14 00:10

Adam Johns


People also ask

What is the significant difference between containsKey () and get ()?

get(Object) does explicitly warn about the subtle differences between Map. get(Object) and Map. containsKey(Object) : If this map permits null values, then a return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null .

Which is better HashMap or ArrayList?

ArrayList stores the elements only as values and maintains internally the indexing for every element. While HashMap stores elements with key and value pairs that means two objects. So HashMap takes more memory comparatively.

What is the difference between ArrayList and HashMap?

The difference between ArrayList and HashMap is that ArrayList is an index-based data-structure supported by array, while the HashMap is a mapped data structure, which works on hashing to retrieve stored values. Although both are used to store objects, they are different in their implementation, function, and usage.

What is containsKey in HashMap Java?

HashMap containsKey() Method in Java HashMap. containsKey() method is used to check whether a particular key is being mapped into the HashMap or not. It takes the key element as a parameter and returns True if that element is mapped in the map.


1 Answers

Hmm does ArrayList.contains() iterate?

/**
 * Returns <tt>true</tt> if this list contains the specified element.
 * More formally, returns <tt>true</tt> if and only if this list contains
 * at least one element <tt>e</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
 *
 * @param o element whose presence in this list is to be tested
 * @return <tt>true</tt> if this list contains the specified element
 */
public boolean contains(Object o) {
    return indexOf(o) >= 0;
}

/**
 * Returns the index of the first occurrence of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the lowest index <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
 * or -1 if there is no such index.
 */
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

Why yes. Yes it does.


Does HashMap.containsKey() iterate?

/**
 * Returns <tt>true</tt> if this map contains a mapping for the
 * specified key.
 *
 * @param   key   The key whose presence in this map is to be tested
 * @return <tt>true</tt> if this map contains a mapping for the specified
 * key.
 */
public boolean containsKey(Object key) {
    return getEntry(key) != null;
}

/**
 * Returns the entry associated with the specified key in the
 * HashMap.  Returns null if the HashMap contains no mapping
 * for the key.
 */
final Entry<K,V> getEntry(Object key) {
    if (size == 0) {
        return null;
    }

    int hash = (key == null) ? 0 : hash(key);
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

No. Well usually not. Kind of? Maybe? If it really has to?

All kidding aside, if you want lookup speed this is where you find it. Only iteration is dealing with very rare hash collisions. If you want that explained look here.


Java 8 Update:

In java 8 ArrayList.contains() ... is the same. Yawn.

But HashMap.containsKey() now uses getNode(). Spiffy.

/**
 * Returns <tt>true</tt> if this map contains a mapping for the
 * specified key.
 *
 * @param   key   The key whose presence in this map is to be tested
 * @return <tt>true</tt> if this map contains a mapping for the specified
 * key.
 */
public boolean containsKey(Object key) {
    return getNode(hash(key), key) != null;
}

/**
 * Implements Map.get and related methods
 *
 * @param hash hash for key
 * @param key the key
 * @return the node, or null if none
 */
final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

It still occasionally iterates, as that while loop will tell you. But, again, this is rare.

I'd give details about the efficiency but that already has an answer here.


HashMap.containsKey() vs HashMap.get()

Since these both delegate the bulk of their work to the same method (genEntry() in 7 & getNode() in 8) I don't think you'll see much performance difference between them. Their iteration behavior will be identical.

If you like your java docs compiled and would rather click than search then try this.

like image 90
candied_orange Avatar answered Oct 12 '22 23:10

candied_orange