HashSet部分:
以下以HashSet为例进行分析。
从Hashset类的主体部分:
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
//这是每个键所指的对像
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<E,Object>();
}
public boolean add(E o) {
return map.put(o, PRESENT)==null;
}
//以下省略..........
}
public HashSet() {
map = new HashMap<E,Object>();
}
可以看到HashSet使用了HashMap作为其Map保存“键-值”对。
请看示例程序4:
import java.util.*;
public class SetTest4 {
public static void main(String[] args){
Set set = new HashSet();
set.add(new SetElement4("aa"));
set.add(new SetElement4("aa"));
set.add(new SetElement4("bb"));
System.out.println(set);
}
static class SetElement4{
String s;
public SetElement4(String s){
this.s = s;
}
public String toString(){
return s;
}
public boolean equals(Object obj) {
return s.equals(((SetElement4)obj).s);
}
}
}
运行结果:
[bb, aa, aa]
没有“示例程序1”中的java.lang.ClassCastException,但是运行结果似乎不对,因为有两个“aa”。
请看示例程序5:
import java.util.*;
public class SetTest5 {
public static void main(String[] args){
Set set = new HashSet();
set.add(new SetElement5("aa"));
set.add(new SetElement5("aa"));
set.add(new SetElement5("bb"));
System.out.println(set);
}
static class SetElement5{
String s;
public SetElement5(String s){
this.s = s;
}
public String toString(){
return s;
}
public boolean equals(Object obj) {
return s.equals(((SetElement5)obj).s);
}
public int hashCode() {
//return super.hashCode();
return s.hashCode();
}
}
}
运行结果:
[bb, aa]
这就对了。“示例程序4”和“示例程序5”有什么区别?是SetElement5重写了hashCode方法。
可见HashSet中是采用了比较元素hashCode的方法来判断元素是否相同(duplicate),而不是采用其他类似equals之类的东东来判断。
说了这么多,那java类库中到底有没有根据equals来判断元素是否相同(duplicate)的Set呢?请看下文。
2.2、CopyOnWriteArraySet部分:
类CopyOnWriteArraySet是java.util.concurrent包中的一个类,所以它是线程安全的。
CopyOnWriteArraySet是使用CopyOnWriteArrayList作为其盛放元素的容器。当往CopyOnWriteArrayList添加新元素,它都要遍历整个List,并且用equals来 比较两个元素是否相同。
请看示例程序6:
import java.util.*;
import java.util.concurrent.*;
public class SetTest6 {
public static void main(String[] args){
Set set = new CopyOnWriteArraySet();
set.add(new SetElement6("aa"));
set.add(new SetElement6("aa"));
set.add(new SetElement6("bb"));
System.out.println(set);
}
static class SetElement6{
String s;
public SetElement6(String s){
this.s = s;
}
public String toString(){
return s;
}
public boolean equals(Object obj) {
return s.equals(((SetElement6)obj).s);
}
}
}
运行结果:
[aa, bb]
好了,一切搞定!!
3、总结:
Javadoc中的一些描述可能是不准确的,大家要当心了!
Set中实现元素互异的各种方法差异很大,大致可以分为三种:使用equals,使用hashCode,使用compareTo。但是我还没有发现采用“判断地址空间是否相同”来判断元素是否相同的类,当然我们可以用现有的三种方法来实现“判断地址空间是否相同”。
综上所述,我们可以总结出使用Set的三种不同的情形:(以下假设元素类为Element)
A、如果想使用Element的equals方法来判断元素是否相同,那么可以使用CopyOnWriteArraySet来构造类的实体。
B、如果Element实现了Comparable接口,而且想使用compareTo方法来判断元素是否相同,那么可以使用TreeSet来构造类的实体。
C、如果想使用判断hashCode是否相同的方法来判断元素是否相同,那么可以使用HashSet来构造类的实体
发表于 @ 2009年12月17日 17:
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pss360/archive/2009/12/17/5026516.aspx
分享到:
相关推荐
- **Set**:Set是无序且不包含重复元素的集合。它不支持索引访问,但提供了一种唯一性保证。常见的Set实现类有HashSet和TreeSet。 2. **retainAll方法的实现原理** - 对于`List`,`retainAll`方法的实现通常是...
set自动将元素进行排序,默认是升序排列,也可以通过自定义比较函数来改变排序规则。set容器的元素在内部是按照红黑树的结构进行存储的,这种数据结构保证了插入、删除和查找操作的效率都是对数级别的。 与set不同...
在`set`容器中,元素不能重复,且元素默认按照升序排列。 #### 三、共同点 1. **底层实现**:在C++ STL中,`map`和`set`都是基于红黑树(Red-Black Tree)实现的。红黑树是一种自平衡二叉查找树,能够保证树的高度...
接下来,我们可以使用以下方法找到这两个数组的交集(即相同元素): 1. **`filter()` 和 `includes()`**:我们可以对其中一个数组进行遍历,然后使用`filter()`方法过滤出另一个数组中包含的元素。 ```javascript...
在Java编程中,处理数据集合时,我们常常会遇到去除重复元素的需求。这可能是为了保持数据的唯一性,或者为了优化存储和计算效率。本文将详细介绍如何在Java中去除重复元素,主要关注数组和列表这两种常见数据结构。...
如果有,就再调用 equals 方法,和 Hash 代码相同的元素比较,元素是否相同。 在选择集合类时,需要考虑集合的特点和性能。ArrayList 适合大量查询的场合,LinkedList 适合大量增删改的场合。HashSet 适合快速查询...
- **insert()**:插入新元素,返回一个迭代器指向新插入的元素,或指向已存在的相同元素。 - **erase()**:删除一个元素或一个范围内的元素,可以基于迭代器或值删除。 #### 元素比较 - **key_comp()**:返回一个...
Set 容器提供了多种比较函数体,用于比较容器中的元素。 * `key_comp()`:获取容器的键比较函数体。 * `value_comp()`:获取容器的值比较函数体。 其他操作函数 Set 容器提供了多种其他操作函数,用于执行各种...
System.out.println("相同元素: " + set1); // 找出array1独有的元素 set1.removeAll(set2); System.out.println("array1独有的元素: " + set1); // 找出array2独有的元素 set2.removeAll(set1); System.out....
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。 记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。 一般情况下,如果自定义的类会产生很多对象,比如...
Python中的集合(Set)是一种非常实用的数据结构,它在概念上类似于数学中的集合,用于存储不重复的元素。集合的特点是没有特定的顺序,且不允许有重复的元素。在Python中,集合是由哈希表(Hash Table)实现的,这...
在Java编程语言中,HashSet是一种常用的集合类,它实现了Set接口,不包含重复元素,并且不保证元素的顺序。在给定的“CustomSet.zip”压缩包中,我们看到一个名为“CustomSet.java”的文件,这很可能是用户自定义的...
在Java编程中,处理整型数组并删除其中的重复元素是一项常见的任务。这通常涉及到集合类的使用,比如HashSet或ArrayList,以及基本的数组操作。本文将深入探讨如何实现这个功能,同时提供一种可能的解决方案。 首先...
哈希集合是一种不包含重复元素的数据结构,适合用来快速查找元素是否存在。滑动窗口则是一种处理数组或序列的方法,可以用来在固定大小的窗口内检查特定条件是否满足。 在提供的代码中,定义了一个名为 `Solution` ...
在C++标准模板库(STL)中,`set`容器是一种非常重要的关联容器,主要用于存储唯一元素,并且这些元素会根据其键值自动排序。`set`内部通常采用红黑树(一种自平衡的二叉查找树)来实现,这使得它在执行插入、删除和...
=`:比较两个`set`是否相等或不等,只有当两个`set`包含相同数量的相同元素时,它们才相等。 - `,`>`,`,`>=`:比较`set`的排序,这在需要对`set`进行排序时很有用。 **5. 成员函数** `set`容器提供了一些有用的...
- **排序与双指针**:如果数组可以排序,可以将两个数组合并并排序,然后使用两个指针,一个指向第一个数组的末尾,另一个指向第二个数组的开头,比较两个指针所指元素,如果相同则为重复元素。 3. **代码实现**:...
本资源主要探讨了`set`的多种用法,包括创建、添加元素、删除元素、集合操作以及在实际编程中的应用。接下来,我们将深入学习`set`的相关知识。 1. **创建Set** 创建一个空集合可以使用`set()`函数,如`my_set = ...
Set是一个不允许有重复元素的集合,它遵循唯一性原则。在Set接口下有许多实现类,如HashSet、TreeSet和LinkedHashSet等。我们以`HashSetDemo.java`为例,探讨HashSet的使用方法。 `HashSet`是Java中最常用的Set实现...