java -- 集合 - 7( Set接口 )

点击查看:java集合(List、Set、Map)博客目录

第七节 : Set接口

java.util.Set接口和java.util.List接口一样。同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行扩充,只是比Collection接口更加严格了。与List接口不同的是:Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。

Set集合有多个子类,这里我们介绍 java.util.HashSet、 java.util.LinkedHashSet 这两个集合。
在这里插入图片描述

  • tips: Set集合取出元素的方式可以采用:迭代器、增强for
7.1 、 HashSet集合介绍
  • java.util.HashSet是Set接口的一个实现类,它所存储的元素是不可重复,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持。
  • HashSet 是根据对象的HashSet值来确定元素在集合中的存储位置,因此具有良好的存储和查找性能。保证元素唯一性的方式依赖于:HashCode与equals方法。
  • 不允许存储重复元素,无索引
  • 是一个无序集合
  • 底层是一个哈希表结构(查询速度非常快)
  • 在这里插入图片描述
/** Set 接口的特点:  无重复元素、无索引
*/
import java.util.*;
public class Main{
    public static void main(String args[]){
        Set<Integer> set = new HashSet<>();
        // 使用add方法 往集合中添加元素
        set.add("1");
	set.add("3");
	set.add("2");
	set.add("1");
	//使用迭代器遍历集合
	Iterator it = set.iterator(); 
	while(it.hasNext()){
	    Integer n = it.next();
	    System.out.println(n);  // 输出:  1  2  3
	}
	//for-each遍历
	for(Integer i:set){
	    System.out.println(i);  // 输出:  1  2  3
	}
    }
}
7.2 、 哈希值

在jdk 1.8之前,哈希表底层采用数组+链表处理冲突,同一hash值的元素都存储在一个链表里,但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而jdk1.8中,哈希表采用 数组+链表+红黑树实现,当链表的长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

import java.util.*;
class Person extends Object{
    /**
      若重写hashCode方法,则按重写后的哈希函数计算。
    */
}
/**哈希值:是一个十进制整数,有系统随机给出(就是对象的地址值,
* 是一个逻辑地址,是模拟出来得到的地址,不是数据实际存储的物理地址)
* 在Object类中有一个方法可以获取哈希码值  
*  public native int hashCode();
*  native :代表该方法调用的是本地操作系统的方法。
*/
public class Main{
    public static void main(String [] args){
        //person类继承了Object类,所以可以使用Object类的hashCode方法
        Person p1 = new  Person();
        int h1 = p1.hashCode();
        Person p2 = new  Person();
        int h1 = p2.hashCode();
        System.out.println(h1);  //  输出: 475266352
        System.out.println(h2);  //  输出: 1355531311

	// String 类的hash值,String 重写了hashCode方法
	String s1 = new String("abc");
	String s1 = new String("abc");
	System.out.println(s1.hashCode());  //  输出: 96354
	System.out.println(s2.hashCode());  //  输出: 96354 
	// hash冲突  
	System.out.println("重地".hashCode());  //  输出:1179395
	System.out.println("通话 ".hashCode());  //  输出:1179395
	
    }
}

在这里插入图片描述

7.3 、 HashSet集合存储数据的结构(哈希表)

在这里插入图片描述

7.4 、 Set集合存储元素不重复的原理
// 创建HashSet集合对象
	HashSet<String> set = new HashSet<>();
	String s1 = "abc";
	String s2 = "abc";
	set.add(s1);
	set.add(s2);
	set.add("重地");
	set.add("通话");
	System.out.println(set);  //  输出:[重地,通话,abc]	

在这里插入图片描述

7.5 、 HashSet存储自定义类型元素

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。

创建自定义Student类:

/* 
   HashSet 存储自定义类型元素
   Set集合元素报错元素唯一:
       存储的元素(String、......Student 、 person ...),必须重写hashCode方法和equals方法。
       同名、同年龄,视为一人,只能存储一次。
*/

class Student{
    private String name;
    private int age;
    
    public Student(){
    }
    public Student(String name , int age){
        this.name = name;
        this.age = age;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    @Override
    public String toString(){
        return "Student{ "+"name = '"+name+'\''+",age = " + age+'}';
    }
}
public class HashSetSaveStudent{
    // 创建hash集合存储Student
    HashSet<Student> set = new HashSet<>();
    Student s1 = new Student("袁睿昕"21);
    Student s2 = new Student("袁睿昕"21);
    Student s3 = new Student("袁睿昕"20);
    set.add(s1);
    set.add(s2);
    set.add(s3);
    System.out.println(set);
    //输出:{Student{name = '袁睿昕',age = 21},name = '袁睿昕',age = 21},name = '袁睿昕',age = 20}}
    // 因为没有重写hashCode方法,so,hashCode不同。
    // so,要添加hashCode和equals方法
   @Override
   public boolean equals(object o){
       if(this == o)  return true;
       if(o == null || getClass() != o.getClass())  return false;
       Student st = (Student) o;
       return age == st.age && Object.equals(name,st.name);  
   }
   @Override
   public int hashCode(){
       return Object.hash(name,age);
   }
   // 添加完以上两个方法后,再次执行结果
   // 输出:{name = '袁睿昕',age = 21},name = '袁睿昕',age = 20}}
}
7.6 、 LinkedHashSet (有序、不允许重复)

我们知道HashSet保证元素唯一,可是元素放进去是没有顺序的,在HashSet下面有一个子类 java.util.LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。
在这里插入图片描述
演示代码如下:

public class LinkedHashSetDemo{
    public static void main(String args[]){
        Set<String> set = new LinkedHashSet<String>();
        set.add("bbb");
        set.add("aaa");
        set.add("abc");
        set.add("def");
        Iterator it = set.iterator();
        while(it.hashNext()){
            System.out.println(it.next());
        }
    }
}
运行结果:
        bbb
        aaa
        abc
        def
发布了52 篇原创文章 · 获赞 7 · 访问量 1789

猜你喜欢

转载自blog.csdn.net/weixin_44107920/article/details/104093235