A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨千里 中级黑马   /  2012-9-4 14:42  /  1871 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨千里 于 2012-9-14 19:54 编辑

Set里的元素是不能重复的,能用==或者equals()区分吗?为什么? 它们有什么区别?

点评

兄弟,请联系相应老师改名!  发表于 2012-9-4 18:49

6 个回复

倒序浏览
本帖最后由 杨习平 于 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比较进行对元素操作。只能是上面所分析的

评分

参与人数 1技术分 +1 收起 理由
田建 + 1

查看全部评分

回复 使用道具 举报
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());           
        }
   }   
}

评分

参与人数 1技术分 +1 收起 理由
田建 + 1

查看全部评分

回复 使用道具 举报
Set是不允许有重复元素的,它是一个借口,一般常用到的实现类就两个,HashSet和TreeSet.

把对象向HashSet中添加的时候,set会调用对象的hashCode方法,得到hashCode后经过一系列的运算得到改对象在集合中的位置.
再次添加对象使,再调用对象hashCode方法,如果这两个对象的HashCode相同,再去调用第二个对象equals()方法,
如果equals方法返回为true,就认为这两个对象的内容是相同的,则把第二个对象丢掉.


向TreeSet里添加的元素必须实现Comparable接口,覆盖compareTo方法,
其实你可以查一下API,往里添加的Integer,String都实现了Comparable
向TreeSet中添加对象的时候,会调用对象的compareTo方法,如果compareTo方法返回为0,就把这个对象丢掉.
用这种形势来保证TreeSet中的数据部重复.
回复 使用道具 举报
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有什么用呢。,用来比较  比较器用的,很少的使用。
   



回复 使用道具 举报
这个具体的测试下就能看出一点不一样了
回复 使用道具 举报
多谢   问题已经解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马