Java Set集合
文章目录
- Java Set集合
- 1 Set 集合
- 2 Set实现类
- 2.1 HashSet【重点】
- 2.2 LinkedHashSet
- 2.3 TreeSet
- 3 Comparator 自定义比较器
1 Set 集合
特点:无序无下标、元素不可重复。
方法:全部继承自Collection中的方法。
常用方法:
public class TestSet01 {
public static void main(String[] args) {
//创建集合
Set<String> set = new HashSet<>();
//1 添加
set.add("苹果");
set.add("香蕉");
set.add("西瓜");
set.add("菠萝");
set.add("桃子");
set.add("榴莲");
//不能添加重复元素
//set.add("苹果");
System.out.println("元素个数: "+set.size());
System.out.println("打印: "+set);
//2 删除
//2.1 删除单个元素
//set.remove("西瓜");
//2.2 清空
//set.clear();
//3 遍历
//3.1 增强for
for (String s : set) {
System.out.println(s);
}
//3.2 迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4 判断
//4.1 判断是否存在
System.out.println(set.contains("榴莲"));
//4.2 判断是否为空
System.out.println(set.isEmpty());
}
}
2 Set实现类
2.1 HashSet【重点】
存储结构: 哈希表(数组+链表),基于hashCode、equals实现元素不重复。
存储过程:
-
根据元素的hash值计算位置,如果这个位置没有元素直接加入。
-
如果有元素会调用equals进行确认,结果为true,拒绝后者存入,如果为false,形成链表。
常用方法:
public class TestHashSet {
static class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
重写规则:
1 equals和hashCode要同时重写
2 两个方法依据的属性保持一致
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
//创建集合
HashSet<Student> hashSet = new HashSet<>();
//创建三个学生对象
Student s1 = new Student("小明", 18);
Student s2 = new Student("小红", 28);
Student s3 = new Student("小白", 21);
Student s4 = new Student("小白", 21);
//1 添加
hashSet.add(s1);
hashSet.add(s2);
hashSet.add(s3);
hashSet.add(s4);
System.out.println("元素个数: "+hashSet.size());
System.out.println("打印: "+hashSet);
//2 删除
//2.1 删除单个元素
//hashSet.remove(s3);
//System.out.println("删除后: "+hashSet);
//2.2 清空
//hashSet.clear();
//3 遍历
//3.1 增强for
for (Student student : hashSet) {
System.out.println(student);
}
//3.2 迭代器
Iterator<Student> it = hashSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4 判断
//4.1 判断是否存在某元素
System.out.println(hashSet.contains(s1));
//4.2 判断是否为空
System.out.println(hashSet.isEmpty());
}
}
2.2 LinkedHashSet
存储结构: 双向链表实现的HashSet,按照链表进行存储,即可保留元素的插入顺序。
常用方法: 与上方一致
LinkedHashSet<Student> set = new LinkedHashSet<>();
2.3 TreeSet
存储结构: 红黑树,基于排序实现元素不重复。
- 对集合元素自动排序。
- 元素的类型必须实现Comparable接口,或自定义比较器。
二叉查找树:
- 一个节点最多只能有两个子节点
- 左节点都比根节点小, 右节点都比根节点大, 没有重复的
- 遍历:
- 先序遍历(根左右);
- 中序遍历(左根右);
- 后序遍历(左右根);
红黑树: 一种特殊的二叉平衡查找树
- 节点有黑色和红色
- 左右保证平衡
常用方法:
public class TestTreeSet {
//静态内部类实现Comparable<?>接口
static class Student implements Comparable<Student> {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
int n1 = this.age-o.age;
int n2 = this.name.compareTo(o.name);
return n1==0?n1:n2;
}
}
public static void main(String[] args) {
//创建集合
TreeSet<Student> treeSet = new TreeSet<>();
//创建四个元素
Student s1 = new Student("小明", 16);
Student s2 = new Student("小红", 21);
Student s3 = new Student("aaa", 19);
Student s4 = new Student("bbb", 19);
//1 添加
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
System.out.println("个数: "+treeSet.size());
System.out.println("打印: "+treeSet);
//2 删除
//treeSet.remove(s4);
//System.out.println("删除后: "+treeSet);
//3 遍历
//3.1 增强for
for (Student student : treeSet) {
System.out.println(student);
}
//3.2 迭代器
Iterator<Student> it = treeSet.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//4 判断
System.out.println(treeSet.contains(s4));
System.out.println(treeSet.isEmpty());
}
}
3 Comparator 自定义比较器
特点:
- 元素自身提供的比较规则称为自然排序。
- Comparator可以实现定制比较规则。
- compare(o1,o2),如果返回值为0,则为重复元素。
- 使用Comparator比较器,元素类型可不实现Comparable接口,并且优先级高于Comparable接口。
//创建比较器,定制比较规则
Comparator<Student> cmp = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int n1 = o1.name.compareTo(o2.name);
int n2 = o1.age- o2.age;
return n1==0?n2:n1;
}
};
//创建集合
TreeSet<Student> treeSet = new TreeSet<>(cmp);
练习:
TreeSet实现字符串按照长度排序,如果长度相同,按照编码顺序。
eg:
public class TestComparator {
public static void main(String[] args) {
//练习:TreeSet实现字符串按照长度排序,如果长度相同,按照编码顺序。
//匿名内部类
Comparator<String> cmp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int n1 = o1.length()-o2.length();
int n2 = o1.compareTo(o2);
return n1==0?n2:n1;
}
};
TreeSet<String> treeSet = new TreeSet<>(cmp);
treeSet.add("aaaaa");
treeSet.add("bbbbb");
treeSet.add("aaa");
treeSet.add("badssd");
treeSet.add("xxxxxxxx");
treeSet.add("aasbv");
System.out.println(treeSet);
}
}
res:
[aaa, aaaaa, aasbv, bbbbb, badssd, xxxxxxxx]