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)领取。