您当前的位置: 首页 >  Java

星夜孤帆

暂无认证

  • 3浏览

    0关注

    626博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java学习笔记(33)-HashSet()与HashCode()

星夜孤帆 发布时间:2018-05-24 22:35:48 ,浏览量:3

Set集合

Set不重复集。无序。

Set不能通过下标获取指定的元素。因为无序所以没有下标。可以使用Iterator的方式迭代集合。

若我们把List看成是有许多格子的盒子,那么Set就好像一个袋子。

hashCode()方法:

hashCode()方法是Object定义的方法。所以每个类都会有该方法。

若我们定义的类重写了equals()方法,就要重写hashCode()方法。

若equals方法返回true,那么这两个对象应该有相同的hashCode值。

反过来不是必须的,但最好是这样。可以提高诸如HashSet这样的数据结构的效率。

eclipse 右键空白处,source,Generate Constructor using Fields自动生成构造方法,不勾选参数,则生成无参构造方法。

source ,Generate Getters and Setter得到get和set方法。

source, Generate hashCode() and equals()生成hashCode()算法并且重写equals方法。

package day04;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * Set集合 无序且不重复集
 * 常用实现类:
 * HashSet:使用散列算法实现的Set集合 哈希
 *
 */
public class DemoSet {
	public static void main(String[] args) {
		/**
		 * 实例化一个HashSet集合
		 */
		Set set = new HashSet();
		/**
		 * 向集合添加元素也使用add
		 * 但是add方法不是向集合末尾追加元素,因为无序
		 */
		set.add("One");
		set.add("Two");
		set.add("Three");
		/**
		 * Set集合没有get(int index)方法
		 * 我们不能像使用List那样,根据下标获取元素。
		 * 像获取元素需要使用Iterator
		 */
		Iterator it = set.iterator();
		while(it.hasNext()){
			String element = it.next();
			System.out.println(element+" ");
		}
		/**
		 * 宏观上讲:元素的顺序和存放顺序是不同的。
		 * 但是在内容不变的前提下,存放顺序是相同的。
		 * 但在我们使用的时候,要当作是无序的使用。
		 */
		
		//使用新循环遍历Set集合
		for(String element:set){
			System.out.println(element);
		}
	}
}

package day04;

public class Point {
	private int x;
	private int y;
	public Point(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	@Override//删了为false
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}
	/**
	 * 若我们不重写hashCode,那么使用的就是Object提供的
	 * 该方法是返回句柄!换句话说,不同的对象hashCode不同
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Point other = (Point) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}
	
}
package day04;

import java.util.HashSet;
import java.util.Set;

/**
 * 测试hashCode对HashSet的影响
 * @author Administrator
 *
 */
public class DemoHashSet {
	public static void main(String[] args) {
		Set set = new HashSet();
		set.add(new Point(1,2));
		set.add(new Point(3,4));
		/**
		 * 查看新创建的对象是否在set中被包含
		 * 虽然这里是新创建的对象,但是通过散列算法找到了位置后
		 * 和里面存放的元素进行equals比较为true,所以依然认为是被包含的。
		 */
		System.out.println(set.contains(new Point(1,2)));
	}
}

package day04;

import java.util.HashSet;
import java.util.Set;

/**
  * HashSet特点
  * @author Administrator
  *
  */
public class DemoHashSet2 {
public static void main(String[] args) {
	/**
	 * 定义一个Set集合,允许里面存放Point实例
	 */
	Set set = new HashSet();
	/**
	 * 创建两个内容一样的对象
	 */
	Point p1 = new Point(1,2);
	Point p2 = new Point(1,2);
	System.out.println("p1和p2是否为同一对象:"+(p1==p2));
	System.out.println("p1和p2内容是否一样:"+p1.equals(p2));
	System.out.println("p1和p2的hashCode是否一样:"+(p1.hashCode()==p2.hashCode()));
	
	/**
	 * 将两个对象同时放入HashSet集合,看看结果怎么样
	 */
	set.add(p1);
	set.add(p2);
	System.out.println("hashset集合的元素数:"+set.size());
	for(Point p: set){
		System.out.println(p);
	}
	/**
	 * 当我们重写了Point的equals方法和hashCode方法后我们发现虽然p1和p2是两个对象,
	 * 但是当我们将他们同时放入集合时,p2对象并没有被添加进集合。因为p1在放入后,p2放入
	 * 时根据p2的hashCode计算的位置中p2与该位置的p1的equals比较为true,HashSet认为该
	 * 对象已经存在,所以拒绝将p2存入集合
	 */
	set.clear();//清除集合元素
	System.out.println("清除了集合。");
	/**
	 * 若我们不重写Point的hashCode方法,但是重写了equals方法,但是重写了equals方法
	 * 两个对象都可以放入HashSet集合中。因为两个对象具有不同的hashcode值,那么当
	 * 他们在放入集合时通过hashcode值进行的散列算法结果就不相同,那么他们会被放入
	 * 集合的不同位置。位置不相同,HashSet则认为他们不同,所以他们可以全部被存入集合。
	 */
	System.out.println("若不重写hashCode方法,添加的效果。");
	set.add(p1);
	set.add(p2);
	System.out.println("set集合的元素数:"+set.size());
	for(Point p:set){
		System.out.println(p);
	}
	set.clear();
	System.out.println("清空集合");
	/**
	 * 若我们重写了hashCode但是不重写equals方法。
	 * hashCode相同的情况下,在存放元素时,他们会在相同的位置,HashSet会在
	 * 相同位置上将后放入的对象与该位置其他对象依次进行equals比较,若不相同,则将其存入。
	 * 在同一个位置存入若干元素,这些元素会被放入一个链表中,由此可以看出。我们应该
	 * 尽量使得多个类的不同对象的hashcode值不同。这样才可以提高HashSet在检索元素时的效率!
	 * 否则可能检索效率还不如List
	 */
	set.add(p1);
	set.add(p2);
	System.out.println("集合的元素数:"+set.size());
	for(Point p : set){
		System.out.println(p);
	}
	/**
	 * 结论:
	 * 使用HashSet集合存放元素时
	 * 应保证:equals与hashCode方法在api上定义的要求
	 * 存放规则:
	 * 不同对象存放时,不会保存hashCode相同并且equals相同的对象。缺一不可。否则HashSet
	 * 不认为他们是重复对象。
	 */
}
}
关注
打赏
1636984416
查看更多评论
立即登录/注册

微信扫码登录

0.0420s