HashSet

首先来看下HashSet的add()这个方法的源代码:

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

由此可知HashSet的值是存储在一个Map的key里面的,而正好Map的key是不能重复的,以下是HashSet的部分源码:

 private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object(); /**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<E,Object>();
} public Iterator<E> iterator() {
return map.keySet().iterator();
} public int size() {
return map.size();
}

接着再看看HashMap里的put()方法是如何判断值是否重复的,以下是HashMap的put()源码:

public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
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;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}

关键这句:if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

它先进行了hashCode的判断,如果hashCode相等再接着使用==来判断传入的对象的引用地址是否相等及使用传入对象的equals()方法来进行判断。

接着再看看HashSet的contains()方法的源码:

public boolean contains(Object o) {
return map.containsKey(o);
}

调用的是Map的containsKey()方法,以下是HashMap的containsKey()源码:

public boolean containsKey(Object key) {
return getEntry(key) != null;
} final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key.hashCode());
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;
}
if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) 和put()方法的判断是一样的。

TreeSet
看看TreeSet的add()方法的源码:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}

它也同样是由一个Map的key来进行存储,看看这个Map:

/**
* The backing map.
*/
private transient NavigableMap<E,Object> m;

接着看看TreeSet的构造函数:

TreeSet(NavigableMap<E,Object> m) {
this.m = m;
} public TreeSet() {
this(new TreeMap<E,Object>());
}

TreeSet的无參构造函数里实例化了一个TreeMap对象,下面看看这个TreeMap对象:

public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{ private final Comparator<? super K> comparator; public TreeMap() {
comparator = null;
} public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
//其他略...
}
public interface NavigableMap<K,V> extends SortedMap<K,V>

接着看这个TreeMap的put()方法:

public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
// TBD:
// 5045147: (coll) Adding null to an empty TreeSet should
// throw NullPointerException
//
// compare(key, key); // type check
root = new Entry<K,V>(key, value, null);
size = 1;
modCount++;
return null;
}
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);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<K,V>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

TreeMap存储的对象是会进行排序的,所以存储的对象都必须实现Comparable接口。

TreeMap先判断Comparator对象是否为空,不为空则使用当前的Comparator对象的compare方法来进行比较排序,若发现compareTo返回的值为0,则认为这两个对象是重复的了,然后覆盖原来的value;如果Comparator对象为空,则使用集合对象实现的Comparable接口的compareTo方法来进行比较排序,同样地当返回值是0时就认为对象重复,然后覆盖原来的value。

 

Set的非重复判断是根据什么判断的的更多相关文章

  1. linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计

    转自:http://blog.sina.com.cn/s/blog_6797a6700101pdm7.html 去除重复行 sort file |uniq 查找非重复行 sort file |uniq ...

  2. sort关于去除重复/查找非重复/查找重复/统计

    去除重复sort file |uniq   查找非重复 sort file | uniq -u   查找重复 sort file | uniq -d   统计 sort file | uniq -c

  3. MySQL(15):Select-distinct(返回非重复的记录)

    1. 查询所有记录 和 查询 非重复记录 语法: SELECT    [ALL | DISTINCT ] All:返回所有记录 Distinct:返回非重复记录 针对获得的记录内的字段生效.   2. ...

  4. leecode第二天-使用异或找出数组中的非重复元素

    leecode题目描述如下: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 思路: 最开始想到的是使用排序,排序之后就很容易找到非重复元素了. ...

  5. [讲解]sql except和intersect运算符(比拟两个或多个select语句的结果并前去非重复值)

    图 1 UNION 中若有重复的行,会被移除,只留下一个 1.简介 EXCEPT和INTERSECT运算符使您可以比较两个或多个SELECT语句的结果并返回非重复值. 2.区别 EXCEPT运算符返回 ...

  6. SSAS 非重复计数

    在SSAS设计时,对商品编号列非重复计数:

  7. 判断密码是否可见/判断登录的状态/判断在form表单中 定义rules规则验证(iview)

    一: 判断密码是否可见判断:type="visiblePassword ? 'text' : 'password'" 是否为false 或者 true 密码为输入框或者文本框点击眼 ...

  8. dfs 全排列 使用交换——含重复元素和非重复元素

    15. 全排列 中文 English 给定一个数字列表,返回其所有可能的排列. 样例 样例 1: 输入:[1] 输出: [ [1] ] 样例 2: 输入:[1,2,3] 输出: [ [1,2,3], ...

  9. mysql删除重复记录,只保留最大ID的记录(非重复也保留)

    目前网上搜索的删除重复记录,大部分都是where子查询,本人感觉看上去不美观,故亲自手写了一个,如下: delete from mst_sku using mst_sku,(  select dist ...

随机推荐

  1. ThinkPHP---TP功能类之公文管理功能2----------继续完善

    [前言] 之前已经完成了公文的添加和列表展示功能,今天继续完善.做下公文的编辑和删除功能. [主体] (1)分析 控制器:DocController.class.php 方法:edit(将模板展示和数 ...

  2. pringboot开启找回Run Dashboard

    代码中加入 <option name="configurationTypes"> <set> <option value="SpringBo ...

  3. Github Pages另一个选择:GitCafe-Pages

    今天找资料时,瞥到了GitCafe-Pages字样,记得前些日子就看到过GitCafe,知道这个是国内的类似Github的代码托管平台,所以一看字样就明白了这个是与Github Pages一样的东东. ...

  4. java基础学习日志--异常案例

    package test7; public class InvalidScroreException extends Exception { public InvalidScroreException ...

  5. [Python数据结构] 使用 Circular List实现Queue

    [Python数据结构] 使用 Circular List实现Queue 1. Queue队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表.在具体 ...

  6. springboot的jsp热部署

    使用springboot每次修改jsp都需要重新启动是不是很麻烦呢?以下是解决办法! yml格式 server: servlet: jsp: init-parameters: development: ...

  7. Linux:DNS主、从、缓存服务器配置、DNS同步加密TSIG配置、DNS分离解析配置

    DNS主服务器配置(正向解析.反向解析) 正向解析:根据主机名查找对应的IP地址.当用户访问一个域名时(不考虑hosts文件等因素),正常情况会向指定的DNS主机发送递归查询请求反向解析:根据IP地址 ...

  8. wake states

    Wake states Table of Contents 1. Turbulent Wake 2. turbulent wake of a circular cylinder 3. Referenc ...

  9. MySQL 分库、分表

    Mysql Sharding 前言 1)Sharding是按照一定规则重新分布数据的方式 2)解决单机写入压力过大和容量问题 3)  解决单机查询慢的问题 4)本文主要根据用户登录场景分析 Shard ...

  10. redis学习——数据类型

    一.内容简介 Redis不仅仅是简单的key-value 存储器,同时也是一种data structures server.传统的key-value是指支持使用一个key字符串来索引value字符串的 ...