Set集合的特点是具有唯一性,那么具体是如何实现的呢,下面将要讨论。
Set 去重原理
继承图
|-- SortedSet接口-----TreeSet实现类
set接口------|-- HashSet实现类
|-- LinkedHashSet实现类
源码中 Set.java 定义了 add() 的抽象方法,具体实现需要看 TreeSet 和 HashSet 的实现
// @return true if this set did not already contain the specified element
boolean add(E e);
TreeSet 去重原理 comparaTo()
下面展示部分源码:TreeSet.java
...
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
...
//@return true if this set did not already contain the specified element
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
调用add()方法时,如果这个set中没有键,添加成功并返回true;否则返回false。
这里用到的m.put(),m实现了Map接口,所以实际上还是使用Map,只不过只使用它的键,而值是一个Dummy value伪值,是常量。
TreeMap.java
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
...
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
...
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
...
} while (t != null);
}
...
}
...
/**
* Compares two keys using the correct comparison method for this TreeMap.
*/
@SuppressWarnings("unchecked")
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
按照调用看下来,最终调用了comparaTo()
。使用二叉树原理,根据比较器的属性去重。如果compareTo返回0,说明是重复的;如果是负数,则往前面排;如果是正数,往后面排。
TreeSet 实例
public class Book implements Comparable<Book>{
private String name;
private double price;
public Book() {
}
public Book(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';