Java Set集合详解与面试点介绍(HashSet、HashLinkedSet、TreeSet)

一、Set接口介绍

set是一个散列集合

Set特点:不包含重复元素, 如果有多个重复元素,只会显示一个。

常用子接口:SortedSet<E>

常用子类:HashSet LinkedHashSet TreeSet

二、HashSet类

(1)HashSet底层数据的数据结构是HashMap,而HashMap的底层是数组+链表的结构。

特点:元素不能重复,元素的位置不是一成不变的,是无序的,线程不安全的

 

(2)HashMap底层存入数据原理:

【1】数据存入HashMap前先进行哈希算法,得到的值,在进行哈希算法(二次哈希),最后得到的结果,在0~15之间(默认的情况下)。

【2】HashMap中每一个数组的位置称之为桶(bucket),数据存入桶之前,会先和桶中的数据进行比较,如果数据相同,那么就舍弃数据,如果数据不同,那么在存入链表中。并且链表是栈结构的(先进后出)。意味着,先进来的在栈尾,后进来的在栈顶。位置改变,所以称之为无序的。

【3】HashMap每次扩容是原来容量的一倍。扩容时会重新进行二次计算,重新排列位置。这个过程称之为rehash

综上所述:元素位置改变有两点:一是链表的栈结构(先进后出),二是扩容时,进行rehash

 

(3)HashSet的初始容量为16,默认加载因子为0.75。当然也可以指定初始容量,与加载因子。

注意如下几点:

如果指定的初始容量过小,会频繁扩容,频繁的计算,效率降低。

如果指定的初始容量过大,会浪费内存。

如果加载因子过小,会频繁扩容。频繁的rehash,就会影响效率

如果加载因子过大,链表的长度会很长,查询速率就降低。

补充:

【1】HashSet指定初始容量,会自动修改为2的n次方的形式。

10 --> 16

15 -->16

7-->8

【2】在JDK1.8后,如果桶上的链表长度大于8,那么会将链表结构扭转为红黑二叉树结构。从而提升效率。

三、LinkedHashSet类

通过翻看LinkedHashSet的源码,我发现,LinkedHashSet中的构造方法,都是调用父类的,而这个父类就是HashSet。所以,它

的初始容量,加载因子扩容方式都是和HashSet一样的。唯一不同的是,它是一个双向链表,其中有一条链表,专门用来控制顺序。

(1)LinkedHashSet是一个有序的集合:存储和取出的顺序相同。因为,它是一个双向链表,专门有一条用来记录顺序。

(2)底层使用数组加链表和一个记录顺序的链表、线程不安全的集合。

(3)默认初始容量为16,默认加载因子为0.75。

 

四、TreeSet类

TreeSet中如果存放的是字符串,会自动进行一个升序排序。因为字符串中实现了Comparable接口,并重写了compareTo方法。

我们可以通过自定义规则,让TreeSet来帮我们进行排序。

如果我们要使用TreeSet进行排序,那么我们的自定义类需要实现Comparable接口,并重写compareTo( )方法。

例:创建学生类并根据学生年龄进行排序

public class TreeDemo {
	
	public static void main(String[] args) {
		Student stu = new Student("张三", 18);
		Student stu1 = new Student("李四", 12);
		Student stu2 = new Student("王五", 20);
		Set<Student> set = new TreeSet<Student>();
		set.add(stu);
		set.add(stu1);
		set.add(stu2);
		for (Student student : set) {
			System.out.println(student);
		}
	}
}
class Student implements Comparable<Student>{
	private String name;
	private int age;
	
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	@Override
	public int compareTo(Student o) {
		return this.age - o.age; 
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	
}

结果:升序排序

Student [name=李四, age=12]
Student [name=张三, age=18]
Student [name=王五, age=20]

实现原理:

compareTo返回值是int类型。

如果返回的是负数,那么表示本对象小于传入的对象,是升序。

如果返回的是正数,那么表示本对象大于传入的对象,是降序。

所以,可以通过交换本对象与传入对象的位置,进行升,降设置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值