0
点赞
收藏
分享

微信扫一扫

javaSE___集合体系07___Set集合下二个子类之____HashSet集合

HashSet集合

一、HashSet存储字符串并遍历

我们知道Set集合是无序的,保证唯一性,不能存储重复的元素。HashSet作为Set的子类,同样如此。

看一下例子就知道了:

/**
     * @param args
     * Set集合,无索引,不可以重复,无序(存取不一致)
     */
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<String>();			//创建HashSet对象
        boolean b1 = hs.add("a");
        boolean b2 = hs.add("a");							//当向set集合中存储重复元素的时候返回为false
        System.out.println(hs);			//输出[a]			//HashSet的继承体系中有重写toString方法
        System.out.println(b1);         //true
        System.out.println(b2);         //false

        hs.add("b");        
        hs.add("c");
        hs.add("d");
        for (String string : hs) {				//只要能用迭代器迭代的,就可以使用增强for循环遍历
            System.out.println(string);         //d,b,c,a
        }
    }

二、HashSet存储自定义对象保证元素唯一性

创建一个Person实体类,有两个属性,一个name,一个age,并生成get、set方法。

public class Person{
	private String name;
	private int age;
	public Person() {
		super();
		
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

测试一下,我们发现它全部都输出了,并不能保证唯一性。

public static void main(String[] args) {

		HashSet<Person> hs = new HashSet<>();
		hs.add(new Person("张三", 23));
		hs.add(new Person("张三", 23));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		
		System.out.println(hs);			//输出上述6个person
	}

  • A:案例演示
    • 存储自定义对象,并保证元素唯一性。

那么我们如何保证唯一性呢?我们只需要重写equals 跟 hashCode方法就可以了,如下:


public class Person{
	private String name;
	private int age;
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	@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) {
		if (this == obj)						
			return true;						
		if (obj == null)						
			return false;						
		if (getClass() != obj.getClass())		
			return false;						
		Person other = (Person) 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;							
	}

测试一下,只有hashCode一样的时候才做比较,才调用equals,如果hashCode不一样,永远不会调用equals方法,保证了唯一性。

public static void main(String[] args) {

		HashSet<Person> hs = new HashSet<>();
		hs.add(new Person("张三", 23));
		hs.add(new Person("张三", 23));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		hs.add(new Person("李四", 24));
		
		System.out.println(hs);			//输出张三23、李四24
	}

三、HashSet如何保证元素唯一性的原理

  • 1.HashSet原理
    • 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
    • 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
      • 如果没有哈希值相同的对象就直接存入集合
      • 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存
  • 2.将自定义类的对象存入HashSet去重复
    • 类中必须重写hashCode()和equals()方法
    • hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    • equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

我们来看一下自动生成重写的 hashCode 跟 equals 代码是什么意思。如下:

/*
	 * 为什么是31?
	 * 1,31是一个质数,质数是能被1和自己本身整除的数
	 * 2,31这个数既不大也不小
	 * 3,31这个数好算,2的五次方-1,2向左移动5位
	 */
	@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) {
		if (this == obj)						//调用的对象和传入的对象是同一个对象
			return true;						//直接返回true
		if (obj == null)						//传入的对象为null
			return false;						//返回false
		if (getClass() != obj.getClass())		//判断两个对象对应的字节码文件是否是同一个字节码
			return false;						//如果不是直接返回false
		Person other = (Person) obj;			//向下转型
		if (age != other.age)					//调用对象的年龄不等于传入对象的年龄
			return false;						//返回false
		if (name == null) {						//调用对象的姓名为null
			if (other.name != null)				//传入对象的姓名不为null
				return false;					//返回false
		} else if (!name.equals(other.name))	//调用对象的姓名不等于传入对象的姓名
			return false;						//返回false
		return true;							//返回true
	}

四、LinkedHashSet的概述和使用

  • LinkedHashSet的特点:
    * 可以保证怎么存就怎么取

例子:

/**
     * @param args
     * LinkedHashSet
     * 底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
     * 因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样
     */
    public static void main(String[] args) {

        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
        lhs.add("a");
        lhs.add("a");
        lhs.add("a");
        lhs.add("a");
        lhs.add("b");
        lhs.add("c");
        lhs.add("d");

        System.out.println(lhs);        //[a, b, c, d]
    }

五、练习:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。

/**
	 * * A:案例演示
	 * 需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复。并把最终的随机数输出到控制台。
	 * 
	 * 分析:
	 * 1,有Random类创建随机数对象
	 * 2,需要存储10个随机数,而且不能重复,所以我们用HashSet集合
	 * 3,如果HashSet的size是小于10就可以不断的存储,如果大于等于10就停止存储
	 * 4,通过Random类中的nextInt(n)方法获取1到20之间的随机数,并将这些随机数存储在HashSet集合中
	 * 5,遍历HashSet
	 */
	public static void main(String[] args) {
		//1,有Random类创建随机数对象
		Random r = new Random();
		//2,需要存储10个随机数,而且不能重复,所以我们用HashSet集合
		HashSet<Integer> hs = new HashSet<>();
		//3,如果HashSet的size是小于10就可以不断的存储,如果大于等于10就停止存储
		while(hs.size() < 10) {
			//4,通过Random类中的nextInt(n)方法获取1到20之间的随机数,并将这些随机数存储在HashSet集合中
			hs.add(r.nextInt(20) + 1);
		}
		// 5,遍历HashSet
		for (Integer integer : hs) {
			System.out.println(integer);
		}
	}

————————

创作不易,如觉不错,随手点赞,关注,收藏(* ̄︶ ̄),谢谢~~

举报

相关推荐

0 条评论