1. 概述
Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
特点
- 不允许存储重复的元素
- 没有索引,没有带索引的方法,也不能使用普通的for循环遍历
- Set集合取出元素的方式可以采用:迭代器、增强for。普通for不行!
Set
集合有多个子类,这里我们介绍其中的HashSet
、LinkedHashSet
这两个集合。
2. HashSet集合
java.util.HashSet
是Set
接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。java.util.HashSet
底层的实现其实是一个java.util.HashMap
支持.
优点
- 具有良好的存取和查找性能:
HashSet
是根据对象的哈希值来确定元素在集合中的存储位置。 - 元素唯一性:依赖于:
hashCode
与equals
方法。
特点
- 不允许存储重复的元素
- 没有索引,没有带索引的方法,也不能使用普通的for循环遍历
- 是一个无序的集合,存储元素和取出元素的顺序有可能不一致
- 底层储数据的结构:哈希表(查询的速度非常的快)
代码:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo01Set {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(1);
// 使用迭代器遍历set集合【不能用for循环,因为没有索引】
Iterator<Integer> it = set.iterator();
while(it.hasNext()) {
Integer n = it.next();
System.out.println(n); // 123
}
System.out.println("=========================");
// 增强for遍历集合
for (Integer i : set) { // set.for
System.out.println(i);
}
}
}
结果:
根据结果我们发现数字1
只存储了一个,也就是说重复的元素set集合不存储。
1
2
3
=========================
1
2
3
3. HashSet存储自定义类型元素
若想在HashSet集合中存放自定义的对象,那么想要保证其唯一,就必须重写hashCode和equals方法建立属于当前对象的比较方式。
必须重写hashCode和equals方法
创建自定义Person类
import java.util.Objects;
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//省略getterandsetter方法和构造器
}
测试类
public class Demo03HashSetSavePerson {
public static void main(String[] args) {
// 创建HashSet集合存储Person
HashSet<Person> set = new HashSet<>();
Person p1 = new Person("小明",18);
Person p2 = new Person("小明",18);
Person p3 = new Person("小明",19);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println("=================");
System.out.println(p1 == p2);
System.out.println(p1.equals(p2)); // 重写equals之前比较的是地址值
System.out.println("=================");
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println(set);
// 遍历
for (Person p : set) {
System.out.println(p);
}
}
}
结果:
- 未重写:
1355531311
1967205423
42121758
=================
false
false
=================
com.luis.demo03.Set.Person@50cbc42f
com.luis.demo03.Set.Person@282ba1e
com.luis.demo03.Set.Person@75412c2f
- 重写后:
23458772
23458772
23458773
=================
false
true
=================
com.luis.demo03.Set.Person@165f3d5
com.luis.demo03.Set.Person@165f3d4
4. LinkedHashSet集合
在HashSet下面有一个子类java.util.LinkedHashSet
,它是**链表和哈希表(数组+链表/红黑树)**组合的一个数据存储结构。可保证集合元素的有序。
演示代码如下:
import java.util.HashSet;
import java.util.LinkedHashSet;
public class Demo04LinkedHashSet {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("www");
set.add("abc");
set.add("abc");
set.add("itcast");
System.out.println(set); // [abc, www, itcast] 无序的,不允许重复
System.out.println("==============");
LinkedHashSet<String> linked = new LinkedHashSet<>();
linked.add("www");
linked.add("abc");
linked.add("abc");
linked.add("itcast");
System.out.println(linked); // [www, abc, itcast] 有序的,不允许重复
}
}
结果:
[abc, www, itcast]
==================
[www, abc, itcast]