java数据结构17_HashSet类详解

1.Set接口介绍

Set接口继承自Collection,Set接口中没有新增方法,方法和Collection保持完全一致。我们在前面通过List学习的方法,在Set中仍然适用。因此,学习Set的使用将没有任何难度。

Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。

Set 集合有多个子类,这里我们介绍其中的 HashSet、LinkedHashSet 、TreeSet这三个集合。

2. HashSet类详解

HashSet是采用哈希算法实现,底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap),因此,查询效率和增删效率都比较高。

我们打开HashSet的源码,发现里面有一行核心代码:
在这里插入图片描述
我们发现里面有个map属性,这就是HashSet的核心秘密。我们再看add()方法,发现增加一个元素说白了就是在map中增加一个键值对,键对象就是这个元素,值对象是名为PRESENT的Object对象。说白了,就是“往set中加入元素,本质就是把这个元素作为key加入到了内部的map中”。
在这里插入图片描述
由于map中key都是不可重复的,因此,HashSet天然具有“不可重复”的特性。

  • HashSet 的使用

给 HashSet 中存储 JavaAPI 中提供的类型元素时,不需要重写元素的 hashCode 和 equals 方法,因为这两个方法,在 JavaAPI 的每个类中已经重写完毕,如 String 类、Integer 类等。

【示例】HashSet存储 String

// 实例化一个set对象
HashSet<String> set = new HashSet<String>();
// 添加元素
set.add("aaa");
set.add("bbb");
set.add("ccc");
set.add("ddd");
set.add("ccc"); // 只能输出一个“ccc”
// 输出元素
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
	System.out.println(iterator.next());
}

输出结果如下,说明set中不能存储重复元素:

aaa
ddd
ccc
bbb

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

【示例】创建自定义对象 Person

class Person {
	String name;
	int age;
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	// 重写equals方法
	@Override
	public boolean equals(Object obj) {
		// 根据内存地址,判断是否相同
		if(this == obj) {
			return true;
		}
		// 判断类型是否为Person,如果不是直接返回false
		if(!(obj instanceof Person)) {
			System.out.println("类型错误");
			return false;
		}
		// 判断属性是否相同
		Person other = (Person) obj;
		return this.age == other.age && this.name.equals(other.name);
	}
	// 重写hashCode方法
	@Override
	public int hashCode() {
		// 返回自定义的hashCode值
		return this.age + this.name.hashCode();
	}
}

【示例】创建 HashSet 集合,存储 Person 对象

public static void main(String[] args) {
	// 实例化一个set对象
	HashSet<Person> set = new HashSet<Person>();
	// 添加自定义对象
	set.add(new Person("张三", 23));
	set.add(new Person("李四", 28));
	set.add(new Person("王麻子", 34));
	set.add(new Person("王五", 33));
	set.add(new Person("王五", 33));  // 只能输出一个“王五”
	// 输出set中的每个元素
	Iterator<Person> iterator = set.iterator();
	while(iterator.hasNext()) {
		Person person = iterator.next();
		System.out.println("name:" + person.name + " age:" + person.age);
	}
}

输出结果如下,说明集合中不能存储重复元素(两个王五只输出一个):

name:王五 age:33
name:张三 age:23
name:王麻子 age:34
name:李四 age:28

3.LinkedHashSet类详解

我们知道 HashSet 保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?

在 HashSet 下面有一个子类 LinkedHashSet,它是链表和哈希表组合的一个数据存储结构。

【示例】LinkedHashSet存储示例

// 实例化一个set对象
LinkedHashSet<Person> set = new LinkedHashSet<Person>();
// 添加自定义对象
set.add(new Person("张三", 23));
set.add(new Person("李四", 28));
set.add(new Person("王麻子", 34));
set.add(new Person("王五", 33));
set.add(new Person("王五", 33)); // 只能输出一个“王五”
// 输出set中的每个元素
Iterator<Person> iterator = set.iterator();
while(iterator.hasNext()) {
	Person person = iterator.next();
	System.out.println("name:" + person.name + " age:" + person.age);
}

输出结果如下,LinkedHashSet 集合保证元素的存入和取出的顺序:

name:张三 age:23
name:李四 age:28
name:王麻子 age:34
name:王五 age:33

ps:如需最新的免费文档资料和教学视频,请添加QQ群(627407545)领取。

发布了35 篇原创文章 · 获赞 0 · 访问量 351

猜你喜欢

转载自blog.csdn.net/zhoujunfeng121/article/details/104562227