黑马程序员技术交流社区
标题:
Set小问题
[打印本页]
作者:
杨千里
时间:
2012-9-4 14:42
标题:
Set小问题
本帖最后由 杨千里 于 2012-9-14 19:54 编辑
Set
里的元素是不能重复的,能用==或者equals()区分吗?为什么?
它们有什么区别
?
作者:
杨习平
时间:
2012-9-4 15:00
本帖最后由 杨习平 于 2012-9-4 15:02 编辑
|--Set 元素无序(存储顺序和取出顺序不一致),不可重复。
|--HashSet
底层数据结构是哈希表。线程不安全。
如何保证元素的唯一性呢?
A:首先根据hashCode值判断。
B:如果hashCode值不同,那么,这就是不同的元素。直接存储。
如果hashCode值相同,那么,会继续根据equals方法进行判断,
根据自己的需求来决定元素是否相同。如果相同,就不存储。
否则,存储。
一般,用HashSet的时候,要重写hashCode和equals方法。
|--LinkedHashSet
底层数据结构是链表和哈希表。
链表用于保证元素有序,哈希表用于保证元素唯一。
|--TreeSet
底层数据结构是二叉树,线程不安全。
如何保证元素的排序呢?两种方式
A:让元素本身具备比较性
实现Compareable接口中的compareTo方法。
B:让集合具备比较性
实现Comparator接口中的compare方法。
所以在Set中 是没有 == 或者用== 和equals比较进行对元素操作。只能是上面所分析的
作者:
冯培军
时间:
2012-9-4 15:07
java_set中实现元素互异的各种方法差异很大,大致可以分为三种:
使用equals,使用hashCode,使用compareTo。
但是还没有发现采用“判断地址空间是否相同”来判断元素是否相同的类,当然我们可以用现有的三种方法来实现“判断地址空间是否相同”。
总结一下使用Set的三种不同的情形:(以下假设元素类为Element)
1、如果想使用Element的equals方法来判断元素是否相同,那么可以使用
CopyOnWriteArraySet
来构造类的实体。
2、如果Element实现了Comparable接口,而且想使用compareTo方法来判断元素是否相同,那么可以使用TreeSet来构造类的实体。
3、如果想使用判断hashCode是否相同的方法来判断元素是否相同,那么可以使用HashSet来构造类的实体。
set使用示例:
import java.util.*;
public class test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set set=new HashSet();
set.add("abc");
set.add("cde");
set.add("efg");
set.add("fgh");
set.add("abc"); //重复的abc,set会自动将其去掉
System.out.println("size="+ set.size() );
List list = new ArrayList();
list.add("abc");
list.add("aaa");
list.add("fff");
set.addAll(list); //将list中的值加入set,并去掉重复的abc
System.out.println("size="+ set.size() );
for( Iterator it = set.iterator(); it.hasNext(); )
{
System.out.println("value="+it.next().toString());
}
}
}
作者:
袁艳超
时间:
2012-9-4 15:14
Set是不允许有重复元素的,它是一个借口,一般常用到的实现类就两个,HashSet和TreeSet.
把对象向HashSet中添加的时候,set会调用对象的hashCode方法,得到hashCode后经过一系列的运算得到改对象在集合中的位置.
再次添加对象使,再调用对象hashCode方法,如果这两个对象的HashCode相同,再去调用第二个对象equals()方法,
如果equals方法返回为true,就认为这两个对象的内容是相同的,则把第二个对象丢掉.
向TreeSet里添加的元素必须实现Comparable接口,覆盖compareTo方法,
其实你可以查一下API,往里添加的Integer,String都实现了Comparable
向TreeSet中添加对象的时候,会调用对象的compareTo方法,如果compareTo方法返回为0,就把这个对象丢掉.
用这种形势来保证TreeSet中的数据部重复.
作者:
李志群
时间:
2012-9-4 15:20
set集合:中的方法和Collection一致,只要重点注重子类的特点。
比较有代表性的容器: 取出只能用迭代器。
HashSet:底层的数据结构是哈希表,不保证顺序,是不同步的。
1.2版本后出来的。
哈希表的由来就是为了提高查询速度。
当哈希值出现相同称为冲突,这时就说明两个元素的位置相同,
再次比较一次两个元素的内同,用equals来完成内容的比较。
如果equals返回的是true视为同一个元素,不存。
如果返回是返回false视为不同元素,存储。
哈希表中的数据必须是唯一的。
哈希表在判断元素或相同的唯一依据是哈希值,如果哈希值相同在判断equals。
哈希表:提供数组的查询效率而出现的。
将要存储的元素先通过哈希算法 算出一个哈希值来标识存储的位置,代表着元素。
要找元素时,先将该元素通过哈希算法算出哈希值,在通过哈希值到哈希表中查询。
特点:
1,不关心元素的顺序。
2,提高查询的效率
3,不可能出现重复元素,因为哈希值都不同,即使相同,会再次进行判断两个元素的equals,内容是否相同
如果内容相同 不存储, 不同就存储。
所以哈希表要保证元素的唯一性,必须要依赖于两个方法。
1,hashCode 2,equals
object类中的hashCode调用的是本地的地址就是系统方法算出来的。
要先覆盖Object类中hashCode方法建立自己对象特点的哈希值算法。
可以直接调用字符串的String类的hashCode方法。
在覆盖equals方法。建立自己的equals。
总结:往哈希表中的存储的自定义对象,必须覆盖hashCode方法和equals方法。
我也不知道这个对象到底存储到那个容器中去。那就将hashCode,equals,toString全部覆盖,‘
不覆盖也从Object类中继承了,那还不如覆盖,创建对子类自身的判断相同的依据。
小细节为了不让判断的哈希值容易出现相同,可以在另一个变量上乘以任意的数,尽量保证哈希值的唯一。
避免老是调用equals方法。
TreeSet:使用元素的自然顺序对元素进行排序。
可以给set集合中的元素进行指定顺序的排序。
默认情况下,是通过元素的自然顺序排的序。
它保证元素唯一性的依据 就是看比较方法的返回结果是否是0,如果是就相同,不是则不同,和equals方法一点关系都没有。
在compareto方法进行对象比较的时候,通常,先比较主要条件,如果主要条件相同,在比较次要条件。
TreeSet:可以给其中的元素进行指定方式排序,使用的自然排序。
自然顺序:就是元素自身的具备的比较性实现了Comparable接口的conpareto方法。
TreeSet排序的方式一:让元素自身具备比较性,需要实现Comparable接口,覆盖compareto方法。
这种比较方式称为自然顺序排序。
排序方式二:如果元素自身不具备比较性或者具备的比较性(自然顺序)不是所需要的,
这是只能用第二种方式。让容器自身具备比较性,容器一初始化就具备比较功能,意味着,容器在对象构造时
完成的,有一个构造方法TreeSet(comparator)在容器初始化时可以指定一个比较器。
需要实现comparator 方法
所以这种方式为比较器排序。
为什么没有覆盖两个方法呢?因为继承了 所以就不用覆盖equals方法了,equals有什么用呢。,用来比较 比较器用的,很少的使用。
作者:
王永杰
时间:
2012-9-5 15:07
这个具体的测试下就能看出一点不一样了
作者:
杨千里
时间:
2012-9-5 16:21
多谢 问题已经解决
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2