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来实现元素不重复,大家有机会可以看看了。
分享到:
相关推荐
set 是一个内部自动有序且不含重复元素的容器。 set 最主要的作用就是自动去重并按升序排序,适用于需要去重但是又不方便直接开数组的情况。 set 中的元素是唯一的,其内部采用“红黑树”实现。 注:本文章只列举 ...
// set容器中的对象不允许重复 // set容器接口的实现类有HashSet和 LinkedHashSet两个 // HashSet不保证迭代顺序, LinkedHashSet按照元素插入的顺序迭代. // 学习List对象容器的使用 // List容器中的对象允许重复 ...
set集合是一个元素无序不重复的序列,可以使用大括号{}或set()函数创建集合。 语法格式: parame={value01,value02,………} 或 set(value) 实例:创建set集合。 #第一种创建set集合 basket={"apple","orange","pear...
Java集合框架中的Set接口是一种不允许包含重复元素的集合。Set接口继承自Collection接口,因此它具有Collection接口定义的所有方法。同时,Set接口还具有自己的特殊方法,例如:添加元素、删除元素、判断元素是否...
总结一下: ArrayList:如果是查改多,用ArrayList LinkedList:如果是增删插多,用LinkedList Vector:如果是有线程安全要求用...LinkedHashSet:如果需要元素不重复,并且,有存入和取出顺序要求用LinkedHashSet
set元素放入无顺序 ,不可重复元素 set与list的对比 set检查元素效率低下,删除和插入的效率高,不会引起元素位置改变 list和数组相似,list可实现动态增长,查找元素效率高,插入和检查的效率低,会
3.Map(映射<集合>)是无序的,是一种把键对象和值对象进行映射的集合,它每一个元素都包含一对键对象和值对象,给出键对象就可以得到值对象,键对象不允许重复,对值没有要求,多个任意键对象可以映射到一个值对象...
关键字class表明定义的是一个类; 类名是类的名称,应是一个合法的标识符; public、protected、private为存取控制属性(访问权限),用来控制对类的 成员的存取。如果前面没有标明访问权限,默认访问权限为private...
方法二:是用set(),set是定义集合的,无序,非重复 方法三:是排序后,倒着扫描,遇到已有的元素删之 #!/usr/bin/python #coding=utf-8 ''' Created on 2012-2-22 Q: 给定一个列表,去掉其重复的元素,并输出 ''' ...
65、Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别 17 66、HashMap和Hashtable的区别 17 67、说出ArrayList,Vector, LinkedList的存储性能和特性 17 68、java中有几...
本文实例讲述了Python实现判断给定列表是否有重复元素的方法。分享给大家供大家参考,具体如下: 题目很简单,只是简单温习一个方法,most_common,这是collection模块中Counter类的方法,具体方法用法可以去查 下面...
· Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制。 · List 接口继承 Collection,允许重复,以元素安插的次序来放置元素,不会重新排列。 · Map接口是一组成对的键-值对象,即所持有...
2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的) 3、List接口有三个...
实现整数集合类 要求: 1、类中含两个私有变量,集合中元素的个数和集合中元素组成的数组。 2、用Set函数输入,Show函数输出结果(按从小到大的顺序输出各个元素...1、集合中不可出现重复元素。 2、空集时,输出empty 。
Set:不允许包含重复元素,通常用于存储不重复的对象集合。 Queue:代表一组按照特定顺序排列的元素,通常用于实现队列和双端队列。 Java标准库中提供了多种实现Collection接口的类,如ArrayList、LinkedList(List...
set是STL中一种标准关联容器,其键值就是实值,实值就是键值,不可以有重复,所以我们不能通过set的迭代器来改变set的元素的值。它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成...
HashSet 是 Java 中的一个集合类,它实现了 Set 接口并提供了基于哈希表的无序、不重复元素的集合。具体来说,它是通过哈希表(实际上是一个 HashMap 实例)来存储元素的。 以下是 HashSet 的一些主要特点: 无序...
对于List好处理,但是对于Set而言我们要如何来保证元素不重复呢?通过迭代来equals()是否相等。数据量小还可以接受,当我们的数据量大的时候效率可想而知(当然我们可以利用算法进行优化)。比如我们向HashSet插入...
Redis的Set是String类型的无序集合,不同于List,Set中的元素不可以重复。Redis 中集合(Set)是通过哈希表(HashTable)实现的,所以添加,删除,查找的复杂度都是 O(1)。 Set的常用操作命令总结 图片来源:...
set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序,如果需要重复则使用multiset,要说区别的话,存储的东西不一样,应用场景不一样,支持的操作也不一样,很多不同。 map和set支持快速查找和...