set的实现类HashSet/TreeSet的底层实现是通过HashMap/TreeMap来实现的。Set的实现类在创建对象的时候都,在构造方法里面都是创建了一个Map的实现类来实现的。而Map中的元素是“键-值”对,其中“键”必须是唯一的。Set就是利用“键”唯一这个特性来实现元素不重复的。它把Set中的元素作为Map的键,从而保持了元素的唯一性。
public class TestTreeSet {
public static void main(String [] args){
Set set = new TreeSet();
set.add(new Element1("aa"));
set.add(new Element1("bb"));
set.add(new Element1("aa"));
}
}
class Element1{
String s ;
public Element1(String s){
this.s = s;
}
@Override
public String toString(){
return s;
}
@Override //这里重写了equals方法,但是实际是没有作用的。
public boolean equals(Object obj) {
return s.equals(((Element1)obj).s);
}
}
// 报错:java.lang.ClassCastException: com.lovo.TestTreeSet$SetElement cannot be cast to java.lang.Comparable
//at java.util.TreeMap.put(TreeMap.java:542)
//at java.util.TreeSet.add(TreeSet.java:238)
//at com.lovo.TestTreeSet.main(TestTreeSet.java:10)
public class TestTreeSet2 {
public static void main(String[] args) {
Set set = new TreeSet();
set.add(new Element2("ss"));
set.add(new Element2("qq"));
set.add(new Element2("ss"));
System.out.println(set);
}
}
class Element2 implements Comparable{
String s;
public Element2(String s){
this.s = s;
}
public String toString(){
return s;
}
public int compareTo(Object o){
return s.compareTo(((Element2)o).s);
}
public boolean equals(Object obj) {
return s.equals(((Element2)obj).s);
}
}
/**
*运行结果:[qq, ss] --达到我们想要的结果。
*TestTreeSet和TestTreeSet2唯一区别就是Element2实现了Comparable接口。进入TreeMap.java:542其实可以看到TreeSet在添加
*元素的时候是使用了TreeMap的put方法。而put方法的实现是通过实现接口Comparable中的CompareTo方法来实现的。所以TreeSet在添加元素
*的时候是把元素cast to Comparable,再来使用compareTo进行比较。
*综合:TreeSet是使用了CompareTo来实现集合中元素不重复。
*/
public class TestTreeSet3 {
public static void main(String[] args) {
Set set = new TreeSet();
set.add(new Element3("ss"));
set.add(new Element3("qq"));
set.add(new Element3("ss"));
System.out.println(set);
}
}
class Element3 implements Comparable{
String s;
public Element3(String s){
this.s = s;
}
public String toString(){
return s;
}
public int compareTo(Object o){
return -1;
}
public boolean equals(Object obj) {
return s.equals(((Element2)obj).s);
}
}
/**
*运行结果:[ss, qq, ss] --没有实现元素不重复。
*原因:重写了compareTo方法返回值是-1,把所有的元素都作为不同的元素处理。
*/
public class TestHashSet1 {
public static void main(String[] args) {
Set set = new HashSet();
set.add(new Element4("kkk"));
set.add(new Element4("jjj"));
set.add(new Element4("kkk"));
System.out.println(set);
}
}
class Element4{
String s;
public Element4(String s) {
super();
this.s = s;
}
@Override
public boolean equals(Object obj) {
return s.equals(((Element4)obj).s);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return s;
}
}
/**
* 运行结果:[jjj, kkk, kkk] --重写了equals没有达到元素不重复的要求
*/
public class TestHashSet2 {
public static void main(String [] args){
Set set = new HashSet();
set.add(new Element5("kkk"));
set.add(new Element5("jjj"));
set.add(new Element5("kkk"));
System.out.println(set);
}
}
class Element5{
String s;
public Element5(String s) {
super();
this.s = s;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return s.hashCode();
}
@Override
public String toString() {
// TODO Auto-generated method stub
return s;
}
@Override
public boolean equals(Object obj) {
return s.equals(((Element5)obj).s);
}
}
/**
* 运行结果:[jjj, kkk]--达到了元素不重复的要求
* 值得注意的是:在类Element5中重写了hashCode方法和equals方法,这两个方法都是不可缺的
* 缺了其中一个就不能达到元素不重复的效果了。
* 看看源码的方法:
* 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;
}
其中的有这样的条件:e.hash == hash && ((k = e.key) == key || key.equals(k))可以看出,如果这个条件成立的话,
那么就是说明元素的重复的,就不会添加元素了。而这个条件所需要的恰好是hashCode方法和equals方法。所以说HashSet实现
元素不重复是使用了:hashCode方法和equals方法。
*/
呵呵,分析的比较粗糙,大家参考哈就是了哈。其实有一个CopyOnWriteArraySet,这个类是AbstractSet的子类。它在实现元素不重复的时候就是用的是List遍历的,采用了equals来实现元素不重复,大家有机会可以看看了。
分享到:
相关推荐
set由于保证元素唯一性,适用于只需要存储不重复单词的场景;而multiset适用于需要统计每个单词出现次数的情况。例题要求输出排序后的单词列表,并且重复的单词只输出一次,set正适合这种情况。 在编程实践中,set...
在`set`容器中,元素不能重复,且元素默认按照升序排列。 #### 三、共同点 1. **底层实现**:在C++ STL中,`map`和`set`都是基于红黑树(Red-Black Tree)实现的。红黑树是一种自平衡二叉查找树,能够保证树的高度...
在实际应用中,`IntSet`常用于各种场景,如数据库索引、算法实现(如图论中的并查集)、统计计算(如不重复计数)等。例如,在网络爬虫中,可以使用`IntSet`来存储已访问过的URL,避免重复抓取;在编译器中,`IntSet...
HashSet是一个不允许有重复元素的集合,当我们尝试将一个数组中的所有元素添加到HashSet时,它会自动过滤掉重复元素。例如: ```java Integer[] array = {1, 2, 3, 2, 4, 3, 5}; Set<Integer> set = new HashSet...
Set是Java集合框架的一部分,主要用于存储不重复的元素。它有多种实现类,如HashSet和TreeSet,每个类都有其特定的特性和用途。 1. **HashSet** - **构造函数**:HashSet提供了多种构造方法,包括无参构造、接受...
在Java编程语言中,HashSet是一种常用的集合类,它实现了Set接口,不包含重复元素,并且不保证元素的顺序。在给定的“CustomSet.zip”压缩包中,我们看到一个名为“CustomSet.java”的文件,这很可能是用户自定义的...
为了确保`School`中的教师实例不重复,开发者最初尝试使用`set`来存储这些实例。然而,由于`set`要求其元素必须是可哈希的,也就是说,这些元素必须拥有`__hash__`方法,而最初的`Teacher`类并没有提供这个方法,...
Python中的集合(Set)是一种非常实用的数据结构,它在概念上类似于数学中的集合,用于存储不重复的元素。集合的特点是没有特定的顺序,且不允许有重复的元素。在Python中,集合是由哈希表(Hash Table)实现的,这...
Set则是一个不包含重复元素的集合,同样支持快速查找。 为了模拟实现Map和Set,我们需要首先封装红黑树。这通常包括以下几个步骤: 1. 定义节点结构:创建一个结构体或类,表示红黑树的节点,包括键、值、颜色、左...
- **Set**:Set是无序且不包含重复元素的集合。它不支持索引访问,但提供了一种唯一性保证。常见的Set实现类有HashSet和TreeSet。 2. **retainAll方法的实现原理** - 对于`List`,`retainAll`方法的实现通常是...
1. HashSet:这是最常用的Set实现,它不保证元素的顺序,允许使用null值,但不允许元素重复。HashSet内部使用哈希表来存储元素,因此添加、删除和查找操作的平均时间复杂度为O(1)。 2. TreeSet:TreeSet基于红黑树...
Set接口是Java集合框架的一部分,它代表了一个数学抽象集合,即不允许包含重复元素的集合。更正式地讲,根据其Javadoc文档,Set是一个不包含任何重复元素的集合。具体来说,Set不允许包含满足`e1.equals(e2)`条件的...
set 是一个内部自动有序且不含重复元素的容器。 set 最主要的作用就是自动去重并按升序排序,适用于需要去重但是又不方便直接开数组的情况。 set 中的元素是唯一的,其内部采用“红黑树”实现。 注:本文章只列举 ...
- **唯一性**:`set`不允许重复元素,尝试插入重复元素时,操作会被忽略。 - **非随机访问**:由于其实现方式,`set`不支持随机访问,只能通过迭代器进行顺序访问。 ### `set`的函数列表 #### 基本操作 - **begin...
Set是一个不允许有重复元素的集合,它遵循唯一性原则。在Set接口下有许多实现类,如HashSet、TreeSet和LinkedHashSet等。我们以`HashSetDemo.java`为例,探讨HashSet的使用方法。 `HashSet`是Java中最常用的Set实现...
### JavaScript 过滤数组重复元素的实现方法 #### 背景介绍 在日常的Web开发工作中,我们经常需要处理各种数据结构,其中数组是最常用的数据类型之一。随着项目的复杂度增加,对于数组中可能出现的重复元素进行有效...
5. 如果当前元素不在哈希集合中,将其添加到 `map` 中,表示该元素进入了滑动窗口。 6. 遍历结束后,如果没有找到符合条件的重复元素,则返回 `False`。 这种方法的时间复杂度为 O(n),空间复杂度也为 O(n),其中 n...
总结来说,集合是Java编程中不可或缺的一部分,而HashSet通过哈希表提供了一种高效存储和检索不重复元素的方式。理解其工作原理对于优化代码性能和解决实际问题具有重要意义。在日常开发中,我们应该根据具体需求...
如果该值已经存在,此操作通常不执行任何操作,因为集合不允许重复元素。 3. **移除数字**: 使用`remove(int value)`方法可以移除集合中的特定整数值。如果该值不存在于集合中,此操作也不会抛出异常。 4. **...
在IT领域,集合是数据结构中的重要组成部分,用于存储不重复的数据。在Java编程语言中,`Set`接口是集合框架的一部分,它继承自`Collection`接口,提供了不允许重复元素的存储功能。在这个主题中,我们将深入探讨`...