HashSet的contains方法
关于HashSet的发现:
1:HashSet是一个Set,也就是所谓的集合。集合的概念是元素在集合中无序、唯一。无序对于计算机来说没有什么意义,因为计算机总要按照一定的顺序存储对象。唯一是怎么实现的呢?名字上说的已经很清楚了。HashSet,就是通过其中的元素(对象)的hashconde来区分对象是否唯一的。所以,HashSet的对象中着一个集合中对象的hashcode的list,每次执行set.add(obj)的时候,都会取出obj的hashcode与其内部的list进行比较,如果没有与之相等的,就加进set里去,同时把那个obj的hashcode加到list里面去;如果有相等的,就再调用obj的equals方法与各个对象进行比较,如果没有相等的,就加入到set里面去,如果还有相等的,就不执行加入操作。
public Set add(Object obj){
int code = obj.hashCode();
if(code not in this.hashcodeList){//如果没有于之相等的hashcode。就将obj加入
this.valueList.add(obj);
this.hashcodeList.add(code);
return true;
}else{//否则看看是否有与之equals相等的。
if(code in this.valueList){//有,add失败
return false;
}else{//没有,add成功
this.valueList.add(obj);
return true;
}
}
}
其实相当于执行了一次contains方法,根据contains方法的返回值决定是否真的add。
也就是说HashSet在确定已经包含某个对象相等的标准是:它们的hashcode相等或者它们的equals方法返回true。
郁闷了半天,怎么先比较hashcode呢?
总算知道了为什么覆盖了toString()后不覆盖hashcode(),Eclipse会给出警告。原来这两个都和对象的相等比较有关系啊。Object的hashcode就是根据对象的内存地址计算出了,保证不重复。而String的hashcode就不一样了,只要字符串的内容相等(equals返回true),它们的hashcode就是相等的。
特别需要注意的是HashSet是有缓存的,第一次contains执行完后会缓存所有的hashcode,以后再调用contains比较的时候使用缓存的hashcode(就是那个list),所以说HashSet最好只用来存储不可变对象,否则contains方法的返回值是不准确的。
一下原则要记住:
1:对于不可变类(String、Integer、以及自己定义的不可变类等),要保证equals返回true的时候,它们的hashcode的值相等。
2:对于不可变类,也要尽量满足1。以避免出现上面说的Set比较时出现的问题。
3:覆盖一个类的equals方法的时候,要注意可交换性,要保证a.equals(b)的值一定等于b.equals(a)的数值。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/DeepNightTwo/archive/2006/07/07/888726.aspx
import java.util.HashSet;
import java.util.Set;
public class Name {
/**
* @param args
*/
private String first,last;
public Name(String first, String last){
this.first = first;
this.last = last;
}
public boolean equals(Object o){
if(!(o instanceof Name))
return false;
Name n = (Name) o;
return n.first.equals(first)&&n.last.equals(last);
}
public static void main(String[] args) {
Name Thomas = new Name("Thomas","Edison");
Name Edison = new Name("Thomas","Edison");
Set s = new HashSet();
s.add(Thomas);
System.out.println(Thomas.equals(Edison));
System.out.println(s.contains(Edison));
System.out.println(Thomas.hashCode());
System.out.println(Edison.hashCode());
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
}
}
结果:
true
false
26399554
7051261
96354
96354
分享到:
相关推荐
1:contains判断去重(有序) 此方法的优点的:理解起来比较简单,并且最终得到的集合也是有序的,这里的有序指的是新集合的排列顺序和原集合的顺序是一致的;但缺点是实现代码有点多,不够简洁优雅。 2:迭代器去重...
HashSet的实现原理 ,HashSet与HashMap的区别 以及 HashSet的底层实现方式
简述了HashSet去重原理
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:
这个是关于java语言的hashset集合类的一些基本用法和详解了个方法的使用
java HashSet 集合排序,需要通过利用TreeSet集合排序。2013-10-30。
hashSet底层去重原理
HashSetHashSetHashSetHashSetHashSetHashSetHashSetHashSetHashSet
treemap treeset hashset hashmap 简要介绍
Set是java中一个不包含重复元素的collection。更正式地说,set 不包含满足e1....HashSet与TreeSet都是基于Set接口的实现类。其中TreeSet是Set的子接口SortedSet的实现类。Set接口及其子接口、实现类的结构如下所示。
HashSet 是一个没有重复元素的集合。 它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素。 HashSet是非同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它...
20220424-笔记-HashSet扩容机制
Qt4.8.5 Bug Patch File
HashSet 是 Java 中的一个集合类,它实现了 Set 接口并提供了...非线程安全:HashSet 类本身不是线程安全的,在多线程环境下需要进行外部同步操作,或者使用 Collections.synchronizedSet 方法封装成线程安全的集合。
源码分析见我博文:http://blog.csdn.net/wabiaozia/article/details/50684556
自己写的例子,关于HashSet遍历和HashMap遍历的. 感谢大家参考
c++一个用vector实现java的HashSet集合类,可以将任何类,数字,字符串,vector等等存放到里面
随机数,HsahSet,排序,输出.随机数,HsahSet,排序,输出.
已设置JavaScript中的简单哈希集创建一个新的HashSet var HashSet = require ( 'hashset' ) ;//Create an empty hash setvar hashset = new HashSet ( ) ;//Create a hash set an initialize it with a value 'a'var...
HashTable不支持空键值对! 而HashMap支持空键值对!