Java容器类中的HashSet

HashSet是一个没有重复元素的集合,不保证元素的顺序,而且HashSet允许有null元素。HashSet是采用哈希算法实现,底层实际是用HashMap实现的,因此,查询效率和增删效率都比较高。

1.Hash算法原理

Hash算法也称之为散列算法。Hash算法就是存储规则的变化,将数据打散。

 26模9=8,放在索引位置为8的位置,15模9=6,放在索引位置为6的位置,22模9=4,放在索引位置为4的位置,24模9为6,已经存在,往后放,放到索引为7的位置。

2.Hash算法的使用

import java.util.Set;
import java.util.*;

public class HashSetTest {
	public static void main(String[] args) {
		//实例化HashSet
		Set<String> set = new HashSet<>();
		//添加元素,注意观察结果,不能有重复元素,添加顺序问题
		set.add("a");
		set.add("b1");
		set.add("c2");
		set.add("d");
		set.add("a");
		//获取元素,在Set容器中,没有索引,所以没有对应的get(int index)方法
		for(String str:set) {
			System.out.println(str);
			
		}
		System.out.println("------删除元素------");
		//删除元素
		boolean flag = set.remove("c2");
		for(String str:set) {
			System.out.println(str);
			
		}
		System.out.println("------元素个数------");
		int size = set.size();
		System.out.println(size);
		//Collection下的接口函数都可以用,参考ArrayList
	}
}
/*
a
d
b1
c2
------删除元素------
a
d
b1
------元素个数------
3
*/

3.HashSet的存储特征

HashSet是一个不保证元素的顺序且没有重复元素的集合,是线程不安全的。HashSet允许有null元素。

无序:

在HashSet中底层是使用HashMap存储元素的,HashMap底层使用的是数组与链表实现元素的存储。元素在数组中存放时,并不是有序存放的也不是随机存放的,而是对元素的哈希值进行运算决定元素在数组中的位置。

数组的默认长度是16,用重写Hashcode的方法,返回 一个int类型的整数,进行哈希算法运算。

不重复:

当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的equals()方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。这里需要注意,这就是为什么说HashMap底层使用的是数组与链表,这里模相同并没有移到下一位,而是利用单向链表进行存储。

4.通过HashSet存储自定义对象

在这里通过HashSet存储自定义对象,注意,如果存储相同的自定义对象需要重写hashCode和equals方法

未重写之前

//Users类
public class Users {
	private String username;
	private int userage;
	public Users(String username,int userage) {
		this.username = username;
		this.userage = userage;
	}
	public Users() {
		
	}
	public void setUsername(String username) {
		this.username=username;
	}
	public String getUsername() {
		return username;
	}
	public void setUserage(int userage) {
		this.userage = userage;
	}
	public int getUserage() {
		return userage;
	}
	@Override
	public String toString() {
		return "Users{"+"username='"+username+'\''+",userage="+userage+'}';
	}
}

重写之后

public class Users {
	private String username;
	private int userage;
	public Users(String username,int userage) {
		this.username = username;
		this.userage = userage;
	}
	public Users() {
		
	}
	public void setUsername(String username) {
		this.username=username;
	}
	public String getUsername() {
		return username;
	}
	public void setUserage(int userage) {
		this.userage = userage;
	}
	public int getUserage() {
		return userage;
	}
	@Override
	public String toString() {
		return "Users{"+"username='"+username+'\''+",userage="+userage+'}';
	}
	@Override 
	public boolean equals(Object o){
		if(this == o ) return true;
		if(o==null||getClass()!=o.getClass()) return false;
		Users users = (Users) o;
		if(userage != users.userage) return false;
		return username != null ? username.equals(users.username):true;
		
	}
	@Override
	public int hashCode() {
		int result = username!=null ? username.hashCode():0;
		result = 31*result+userage;
		return result;
		
	}
}

测试

public class HastSetTest02 {
	public static void main(String[] args) {
		//实例化Hashset
		Set<Users> set = new HashSet<>();
		Users u1 = new Users("li1",3);
		Users u2 = new Users("li1",3);
		set.add(u1);
		set.add(u2);
		//观察哈希值,不相同,解决方法是重写equals和hashCode代码
		System.out.println(u1.hashCode());
		System.out.println(u2.hashCode());
		for(Users u:set) {
			System.out.println(u.toString());
		}
		
	}
}
/*
未重写结果
793589513
1313922862
Users{username='li1',userage=3}
Users{username='li1',userage=3}
重写结果
3319855
3319855
Users{username='li1',userage=3}
*/

おすすめ

転載: blog.csdn.net/lipengfei0427/article/details/121524687