`

HashSet的contains方法引出来的东东

阅读更多
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


分享到:
评论

相关推荐

    hashset类的使用

    然后使用contains方法检查HashSet中是否包含特定字符串。我们还演示了remove方法来删除一个元素,使用size方法获取了HashSet中元素的数量,并最终使用迭代器遍历了HashSet中的所有元素。 在实际应用中,HashSet因其...

    HashSet类的用法.pdf

    如果多个线程同时对一个`HashSet`进行修改操作,那么必须采取额外措施(如使用`synchronized`关键字或`Collections.synchronizedSet()`方法)来保证线程安全。 3. **允许一个null元素**:`HashSet`允许存在一个`null...

    List 去重的6种方法(contains、迭代、hashSet、treeSet、linkedHashSet、stream)

    1:contains判断去重(有序) 此方法的优点的:理解起来比较简单,并且最终得到的集合也是有序的,这里的有序指的是新集合的排列顺序和原集合的顺序是一致的;但缺点是实现代码有点多,不够简洁优雅。 2:迭代器去重...

    HashSet的实现原理

    这种实现方式让HashSet的操作非常简单高效,因为HashSet的大部分操作,包括添加元素、删除元素、检查元素是否存在等,都是直接调用HashMap的相关方法来完成的。 首先,我们来详细了解一下HashSet的基本概念和结构。...

    HashSet去重

    - **`equals`方法的作用**:当两个对象的`hashCode`相同时,`HashSet`会调用这两个对象的`equals`方法来最终确定是否为同一个对象。 - **效率问题**:对于大量数据而言,`HashSet`的效率非常高。哈希表通过`hashCode...

    HashSet详解和使用示例_动力节点Java学院整理

    - `contains(Object object)`:判断HashSet是否包含指定的元素。 - `isEmpty()`:检查HashSet是否为空。 - `iterator()`:返回一个迭代器,用于遍历HashSet的元素。 - `remove(Object object)`:移除HashSet中指定的...

    集合类HashSet

    然后,通过HashSet的contains()方法查找对象;最后,如果找到了该对象,就可以直接调用其方法。例如: ```java HashSet<MyObject> set = new HashSet(); MyObject obj = new MyObject(); set.add(obj); if (set....

    HashMap与HashTable和HashSet的区别

    - **线程安全性**:`HashTable`的所有方法都是同步的,因此它是线程安全的。 - **初始容量和加载因子**:可以通过构造函数设置`HashTable`的初始容量和加载因子。默认情况下,加载因子为0.75,这是一个很好的平衡点...

    HashSet工作原理_动力节点Java学院整理

    对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:

    源码解析jdk7.0集合:HashSet的底层实现原理.pdf

    在HashSet中,当调用add()方法时,它会检查新元素的hashCode()值,如果该值对应的HashMap位置上已经存在元素,则再调用equals()方法来判断是否真正重复。如果equals()方法返回true,则说明当前元素与已存在元素相等...

    Java中ArrayList的removeAll方法详解

    这是因为优化的方法使用了HashSet的contains方法,该方法的时间复杂度为O(1),far less than O(n)。同时,优化的方法也使用了迭代器遍历ArrayList中的元素,而不是使用循环遍历。这也提高了方法的执行速度。 ...

    c++用vector实现HashSet

    在C++编程中,HashSet是一种常用的集合数据结构,它提供了存储唯一对象的功能,类似于Java中的HashSet。虽然C++标准库中没有直接提供HashSet类,但我们可以利用其他容器,如`std::unordered_set`来实现类似的功能。...

    treemap treeset hashset hashmap 简要介绍

    为了正确地工作,`HashSet`要求元素具有良好的`equals()`和`hashCode()`方法实现,以确保元素的唯一性和性能。`HashSet`的底层使用了`HashMap`,实际上,`HashSet`内部就是一个`HashMap`,其中所有值都被设置为`null...

    java 利用HashSet删除学生

    HashSet类提供了添加元素(add())、删除元素(remove())、检查元素是否存在(contains())等方法。在删除学生这个场景中,我们通常会有一个表示学生的类,例如`Student`,它包含一些属性如学号(id)、姓名(name...

    java HashSet 集合排序

    java HashSet 集合排序,需要通过利用TreeSet集合排序。2013-10-30。

    Java基础加强_ArrayList_HashSet的比较及Hashcode分析

    当两个对象的Hashcode相同,HashSet会调用equals()方法进一步判断它们是否真的相等。 Hashcode是一个关键的概念,它是Java中的一个方法,用于将对象映射到一个整数值,通常用于哈希表的实现。每个对象都有一个唯一...

    hashSet底层去重原理.xmind

    hashSet底层去重原理

    排序之HashSet和TreeSet的区别

    在Java编程语言中,集合框架是处理数据的重要组成部分,其中`...同时,源码阅读也是提升技能的好方法,通过查看`HashSet`和`TreeSet`的源码,可以更深入地了解它们的工作原理,这有助于优化代码并解决可能出现的问题。

    Java中HashSet的解读_.docx

    HashSet的主要操作,如添加元素(add)、删除元素(remove)、检查元素是否存在(contains)等,都直接委托给了HashMap。例如,`add()`方法实质上是调用了HashMap的`put()`方法,如果元素不在HashSet中,`put()`会...

    集合的概念及应用和HashSet保证数据不重复的原理

    同时,源码分析也能帮助我们理解HashMap的扩容机制,以及为什么即使两个对象的hashCode相同,它们仍然可以在HashSet中区分(因为equals()方法的正确实现)。 工具在学习和使用集合框架时也扮演着重要角色。例如,...

Global site tag (gtag.js) - Google Analytics