我们经常使用的集合如ArrayList,LinkedList,Vector, **你在调用contains()方法的时候, 或者是你在根据对象移除元素 remove(Object o) 你知道他们是如何判断集合中的元素是否 是相等的吗**? 接下来我们跟着源码去详细探究一下 数据数据结构不同判断的依据就不同,我们先来看一下List类的判断依据.
先简单的了解一下 List类 : 有序,可以有重复元素。
ArrayList 底层是一个对象数组 PRivate transient Object[] elementData;
LinkedList 属于链式数据结构,底层用的是一个Node类的节点,包括指针域和数据域.
private static class Node { E item; Node next; Node prev;
Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; }}ArrayList LinkedList他们都是线程不同步的 Vector非常类似ArrayList,但是Vector是同步的。, ArrayList LinkedList多线程访问会抛出 ConcurrentModificationException。如果想使他们线程同步的可以使用 Collections.synchronizedList 方法将该集合“包装”起来
回归正题
我们想知道他们如何判断集合元素是否相等,我们应该想到的是contains(Object o)方法,接下来我们看一下contains(Object o)方法
public boolean contains(Object o) { return indexOf(o) >= 0; }他的方法内部调用了indexOf(o)这个方法,我们继续追踪看一下indexOf(o)方法
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; }看到这里我们应该能明白了 先判断要查找的元素是否为空,不为空的话就调用equals方法.由此我们得到一个结论 List类中判断元素是否相等依赖的是equals方法.
set类 : 无序,不允许重复
HashSet : 此实现不是同步的 我们知道HashSet它不允许出现重复元素,他是如何保证元素唯一的呢,我们应该首先想到的是看他的add()方法 如下
public boolean add(E e) { return map.put(e, PRESENT)==null; }
这里出现了一个map我们找找看看他是什么
我们在上面看到了他的定义
private transient HashMap<E,Object> map;现在我们知道了HashSet的内部其实是一个HashMap来维护的,众所周知HashMap的键是不允许有相同的,不用说HashMap的键就是HashSet的值,接下来我们只需要知道HashMap的键是如何保证唯一的就行了
我们就要追踪HashMap的添加元素方法 put(K key, V value)
public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = hash(key); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordaccess(this); return oldValue; } }虽然有点麻烦我们只需要仔细看看 一定可以看明白 抓住最重要的一句
e.hash == hash && ((k = e.key) == key || key.equals(k))现在我们也知道了HashSet 和HaspMap 保证元素唯一的办法是 先比较两个元素的哈希值,如果哈希值相等,在比较元素的地址是否相同,或者调用两个元素的equals方法如果哈希值不同,就根本不用在比较了.
新闻热点
疑难解答