java Set 类,hashSet类, hashCode方法

集合中,Set里面存储的元素不能重复,没有索引,存取顺序不一致。

Set的继承关系图如下

Set接口继承了Collection接口,

HashSet存放无序,不重复的元素常用方法

boolean add(E e)  添加一个元素,返回一个布尔值,如果添加的元素在Set中存在,则添加不了,返回false

add的实现是先调用对象的hashCode方法,如果返回的hashCode值相同,再调用equals方法,判断添加的元素是否在Set中存在,存在则不添加,不存在则添加.如果返回的hashCode值不同,就直接将元素添加到Set中,所以添加的元素要重写hashCode()和equals()方法

int size() 返回Set的元素个数

void clear() 清空Set中所有元素

boolean contains(Object o) 返回Set中是否包含了特定元素

boolean isEmpty()   检查Set中是否没有元素,没有就返回true,有就返回false
Iterator<E> iterator() 生成Set的迭代器对象

boolean remove(Object o) 在Set中删除特定元素,如果此元素在Set中返回true,如果Set中没有此元素返回false

示例:

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

public class HashSetTest01 {
	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		boolean b1 = set.add("a");
		boolean b2 = set.add("a");
		System.out.println(b1);// true
		System.out.println(b2);// false
		set.add("c");
		set.add("f");
		set.add("b");
		for (String s : set) {
			System.out.print(s + " ");
		} //打印结果为a b c f 可以看到跟Set中的元素跟存放顺序无关 

	}
}
out:
true
false
a b c f 

hashCode()方法

hashCode方法可以配合基于散列的集合,这样的散列集合一般使用在hash容器中包括HashSet、HashMap以及HashTable.

HashCode方法的作用就是将对象均匀散列分类,然后获取到编号值,

类似于下图,将相同或者相似对象归为一类(hash code相同),再用equals方法判断是否相同

equals方法和hashCode方法 的关系

在Map和Set这种存储不重复元素的容器中,equals方法本来是可以比较出两个对象是否相同,但是如果对象的个数太多的话,会影响性能,所以hashCode()可以先来一个预先判断,将对象hashCode方法返回的hash code存储在hash表中,下个对象hashCode方法返回的hash code如果在hash表中能找到,进行equals比较,如果hash表不存在此hash code,  说明这个对象没有跟以前的重复,不需要进行equals比较

为什么有了hashCode()方法还要equals方法,是因为hashCode()方法并不是完全可靠,不同对象的hash code值可能相同

 重写hashCode()方法的必要性      Object类中的hashCode()方法只是返回当前对象的地址,相同的一个类,new创建两个对象,由于他们在内存里的地址不同,则他们的hashCode()不同,这显然达不到我们想要hsahCode()预判断的效果,所以要重写hashCode()

针对Set,Map这种类型的容器,重写equals()方法时也要重写hashCode()方法

重写hashCode方法时要注意:

  • 相等的对象(equals比较为true)必须具有相等的散列码(hash code)。
  • 不等的对象(equals比较为false),散列码(hash code)值可以相等也可以不相等.
  • 任何时候对同一对象多次调用 hashCode 方法,都必须一直返回同样的整数 

 示例:

package students;

public class Student {
	private int age;
	private String name;

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}
        //eclipse自动生成的hashCode方法
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		System.out.println("equals");
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
}
//测试类
import java.util.HashSet;
import java.util.Set;

import students.Student;

public class HashSetTest02 {
	public static void main(String[] args) {
		Set<Student> set = new HashSet<>();
		set.add(new Student(12, "张三"));
		set.add(new Student(13, "李四"));
		set.add(new Student(14, "赵五"));
		set.add(new Student(12, "张三"));
		set.add(new Student(13, "李四"));
		System.out.println(set); // 如果对象类没有重写hashCode,Set不会去重,会把所有元素添加到Set中
									// 对象类重写hashCode方法后,Set就会去重

	}
}
out:
equals
equals
[Student [age=14, name=赵五], Student [age=12, name=张三], Student [age=13, name=李四]]

当自定义的类只有int age和String name这两个属性时,eclipse自动生成的hashCode方法:

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

 为什么eclipse自动重写的hashCode方法中的prime为31?

     其实这个值改成别的也可以,只不过定义为31之后有一些好处:

  • 31是一个质数,质数是能被1和自己本身整除的数,并且这个数不大也不小
  • 31这个数好算,2的五次方-1,2向左移动5位

参考 :  http://www.monkey1024.com/javase/573

猜你喜欢

转载自blog.csdn.net/sinat_41132860/article/details/84201265