`
sunlujing
  • 浏览: 180070 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Set 如何比较重复元素

 
阅读更多

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

分享到:
评论

相关推荐

    List和Set使用retainAll方法的比较

    - **Set**:Set是无序且不包含重复元素的集合。它不支持索引访问,但提供了一种唯一性保证。常见的Set实现类有HashSet和TreeSet。 2. **retainAll方法的实现原理** - 对于`List`,`retainAll`方法的实现通常是...

    C++set函数学习

    set自动将元素进行排序,默认是升序排列,也可以通过自定义比较函数来改变排序规则。set容器的元素在内部是按照红黑树的结构进行存储的,这种数据结构保证了插入、删除和查找操作的效率都是对数级别的。 与set不同...

    map和set的异同

    在`set`容器中,元素不能重复,且元素默认按照升序排列。 #### 三、共同点 1. **底层实现**:在C++ STL中,`map`和`set`都是基于红黑树(Red-Black Tree)实现的。红黑树是一种自平衡二叉查找树,能够保证树的高度...

    比较json对象中的两个数组含有的相同元素,点击按钮输出新的数组

    接下来,我们可以使用以下方法找到这两个数组的交集(即相同元素): 1. **`filter()` 和 `includes()`**:我们可以对其中一个数组进行遍历,然后使用`filter()`方法过滤出另一个数组中包含的元素。 ```javascript...

    java 去除重复元素

    在Java编程中,处理数据集合时,我们常常会遇到去除重复元素的需求。这可能是为了保持数据的唯一性,或者为了优化存储和计算效率。本文将详细介绍如何在Java中去除重复元素,主要关注数组和列表这两种常见数据结构。...

    List Set Map以及子类的比较 .docx

    如果有,就再调用 equals 方法,和 Hash 代码相同的元素比较,元素是否相同。 在选择集合类时,需要考虑集合的特点和性能。ArrayList 适合大量查询的场合,LinkedList 适合大量增删改的场合。HashSet 适合快速查询...

    C++ 集合 set 例子

    - **insert()**:插入新元素,返回一个迭代器指向新插入的元素,或指向已存在的相同元素。 - **erase()**:删除一个元素或一个范围内的元素,可以基于迭代器或值删除。 #### 元素比较 - **key_comp()**:返回一个...

    stl_set容器详细使用方法

    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....

    java集合知识-map、set等

    如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。 记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。 一般情况下,如果自定义的类会产生很多对象,比如...

    python内置的集合set中元素顺序-python基础教程:set(集合).pdf

    Python中的集合(Set)是一种非常实用的数据结构,它在概念上类似于数学中的集合,用于存储不重复的元素。集合的特点是没有特定的顺序,且不允许有重复的元素。在Python中,集合是由哈希表(Hash Table)实现的,这...

    CustomSet.zip

    在Java编程语言中,HashSet是一种常用的集合类,它实现了Set接口,不包含重复元素,并且不保证元素的顺序。在给定的“CustomSet.zip”压缩包中,我们看到一个名为“CustomSet.java”的文件,这很可能是用户自定义的...

    删除定制整型数组中重复元素输出剩余元素

    在Java编程中,处理整型数组并删除其中的重复元素是一项常见的任务。这通常涉及到集合类的使用,比如HashSet或ArrayList,以及基本的数组操作。本文将深入探讨如何实现这个功能,同时提供一种可能的解决方案。 首先...

    219. 存在重复元素 II(set+滑窗)1

    哈希集合是一种不包含重复元素的数据结构,适合用来快速查找元素是否存在。滑动窗口则是一种处理数组或序列的方法,可以用来在固定大小的窗口内检查特定条件是否满足。 在提供的代码中,定义了一个名为 `Solution` ...

    C++_STL之set容器使用方法

    在C++标准模板库(STL)中,`set`容器是一种非常重要的关联容器,主要用于存储唯一元素,并且这些元素会根据其键值自动排序。`set`内部通常采用红黑树(一种自平衡的二叉查找树)来实现,这使得它在执行插入、删除和...

    STL_set.rar_stl set

    =`:比较两个`set`是否相等或不等,只有当两个`set`包含相同数量的相同元素时,它们才相等。 - `,`&gt;`,`,`&gt;=`:比较`set`的排序,这在需要对`set`进行排序时很有用。 **5. 成员函数** `set`容器提供了一些有用的...

    java 求两个数组中重复元素源代码

    - **排序与双指针**:如果数组可以排序,可以将两个数组合并并排序,然后使用两个指针,一个指向第一个数组的末尾,另一个指向第二个数组的开头,比较两个指针所指元素,如果相同则为重复元素。 3. **代码实现**:...

    set的用法的源代码资源

    本资源主要探讨了`set`的多种用法,包括创建、添加元素、删除元素、集合操作以及在实际编程中的应用。接下来,我们将深入学习`set`的相关知识。 1. **创建Set** 创建一个空集合可以使用`set()`函数,如`my_set = ...

    c++类set精讲和详解

    `set`中的元素会被自动按照键值进行排序,这种排序是通过比较运算符 `实现的。一旦元素插入到`set`容器中,其值就不能被更改。 #### 二、set容器的基本特性 1. **动态大小**:`set`容器的大小可以根据需要动态变化...

    Set用法及与List的区别

    Set是一个不允许有重复元素的集合,它遵循唯一性原则。在Set接口下有许多实现类,如HashSet、TreeSet和LinkedHashSet等。我们以`HashSetDemo.java`为例,探讨HashSet的使用方法。 `HashSet`是Java中最常用的Set实现...

Global site tag (gtag.js) - Google Analytics