`
lihengzkj
  • 浏览: 44234 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

关于SET元素不重复的实现

阅读更多
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来实现元素不重复,大家有机会可以看看了。
分享到:
评论

相关推荐

    C++ Set(集合)

    set 是一个内部自动有序且不含重复元素的容器。 set 最主要的作用就是自动去重并按升序排序,适用于需要去重但是又不方便直接开数组的情况。 set 中的元素是唯一的,其内部采用“红黑树”实现。 注:本文章只列举 ...

    java中set、list和map的使用方法实例

    // set容器中的对象不允许重复 // set容器接口的实现类有HashSet和 LinkedHashSet两个 // HashSet不保证迭代顺序, LinkedHashSet按照元素插入的顺序迭代. // 学习List对象容器的使用 // List容器中的对象允许重复 ...

    Python语言基础:set集合运用.pptx

    set集合是一个元素无序不重复的序列,可以使用大括号{}或set()函数创建集合。 语法格式: parame={value01,value02,………} 或 set(value) 实例:创建set集合。 #第一种创建set集合 basket={"apple","orange","pear...

    Java集合框架Set接口.pdf

    Java集合框架中的Set接口是一种不允许包含重复元素的集合。Set接口继承自Collection接口,因此它具有Collection接口定义的所有方法。同时,Set接口还具有自己的特殊方法,例如:添加元素、删除元素、判断元素是否...

    day016-list和set笔记以及代码.zip

    总结一下: ArrayList:如果是查改多,用ArrayList LinkedList:如果是增删插多,用LinkedList Vector:如果是有线程安全要求用...LinkedHashSet:如果需要元素不重复,并且,有存入和取出顺序要求用LinkedHashSet

    List、Set、Map的特点及遍历方法

    set元素放入无顺序 ,不可重复元素 set与list的对比 set检查元素效率低下,删除和插入的效率高,不会引起元素位置改变 list和数组相似,list可实现动态增长,查找元素效率高,插入和检查的效率低,会

    set.list.map接口

    3.Map(映射&lt;集合&gt;)是无序的,是一种把键对象和值对象进行映射的集合,它每一个元素都包含一对键对象和值对象,给出键对象就可以得到值对象,键对象不允许重复,对值没有要求,多个任意键对象可以映射到一个值对象...

    c++ 类与对象课件,包括对象的初始化,对象的使用,构造函数和析构函数等等

    关键字class表明定义的是一个类; 类名是类的名称,应是一个合法的标识符; public、protected、private为存取控制属性(访问权限),用来控制对类的 成员的存取。如果前面没有标明访问权限,默认访问权限为private...

    Python代码实现删除一个list里面重复元素的方法

    方法二:是用set(),set是定义集合的,无序,非重复 方法三:是排序后,倒着扫描,遇到已有的元素删之 #!/usr/bin/python #coding=utf-8 ''' Created on 2012-2-22 Q: 给定一个列表,去掉其重复的元素,并输出 ''' ...

    java面试宝典

    65、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别 17 66、HashMap和Hashtable的区别 17 67、说出ArrayList,Vector, LinkedList的存储性能和特性 17 68、java中有几...

    Python实现判断给定列表是否有重复元素的方法

    本文实例讲述了Python实现判断给定列表是否有重复元素的方法。分享给大家供大家参考,具体如下: 题目很简单,只是简单温习一个方法,most_common,这是collection模块中Counter类的方法,具体方法用法可以去查 下面...

    JAVA集合(List,Set,Map)

     · Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制。 · List 接口继承 Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。 · Map接口是一组成对的键-值对象,即所持有...

    JAVA中List与Set、Map的区别

     2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)  3、List接口有三个...

    整数集合类与复数集合类 c++代码实现

    实现整数集合类 要求: 1、类中含两个私有变量,集合中元素的个数和集合中元素组成的数组。 2、用Set函数输入,Show函数输出结果(按从小到大的顺序输出各个元素...1、集合中不可出现重复元素。 2、空集时,输出empty 。

    基础深化和提高-java容器

    Set:不允许包含重复元素,通常用于存储不重复的对象集合。 Queue:代表一组按照特定顺序排列的元素,通常用于实现队列和双端队列。 Java标准库中提供了多种实现Collection接口的类,如ArrayList、LinkedList(List...

    c++ STL库容器之集合set代码实例

    set是STL中一种标准关联容器,其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值。它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成...

    java集合-HashSet的使用

    HashSet 是 Java 中的一个集合类,它实现了 Set 接口并提供了基于哈希表的无序、不重复元素的集合。具体来说,它是通过哈希表(实际上是一个 HashMap 实例)来存储元素的。 以下是 HashSet 的一些主要特点: 无序...

    HashCode作用_动力节点Java学院整理

    对于List好处理,但是对于Set而言我们要如何来保证元素不重复呢?通过迭代来equals()是否相等。数据量小还可以接受,当我们的数据量大的时候效率可想而知(当然我们可以利用算法进行优化)。比如我们向HashSet插入...

    Redis的五大数据类型之集合(Set)的总结

    Redis的Set是String类型的无序集合,不同于List,Set中的元素不可以重复。Redis 中集合(Set)是通过哈希表(HashTable)实现的,所以添加,删除,查找的复杂度都是 O(1)。 Set的常用操作命令总结 图片来源:...

    Map和Set的区别

    set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序,如果需要重复则使用multiset,要说区别的话,存储的东西不一样,应用场景不一样,支持的操作也不一样,很多不同。  map和set支持快速查找和...

Global site tag (gtag.js) - Google Analytics