Java set集合讲解
-
基于双向链表实现.
-
默认不保证顺序(除
LinkedHashSet
和TreeSet
) -
不可重复: 可用来去重
-
无索引, 不能使用普通
for
循环遍历, 不提供基于索引的访问
三个实现类
-
HashSet
: 无序,不重复,无索引,基于哈希表实现. -
LinkedHashSet
: 有序,不重复,无索引,HashSet的子类. -
TreeSet
: 可排序,不重复,无索引,基于红黑树实现.
Set的遍历
- 迭代器
- 增强
for
Lambda
表达式
import java.util.*; public class javatest { public static void main(String[] args) { Set<String> set = new HashSet<>(); System.out.println(set.add("a"));//有返回值,第一次添加成功返回true,第二次添加失败返回false //System.out.println(set.add("a"));//false set.add("b"); set.add("c"); //迭代器Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } //增强for循环 for (String string : set) { System.out.println(string); } //lambda表达式set.forEach(System.out::println); }
}
HashSet
-
底层采用哈希表的方式储存数据, 哈希表对于增删改查的性能都比较好
-
哈希表实现: jdk8以前是数组+链表, jdk8以后是数组+链表+红黑树
特性
-
不重复:
HashSet
中的元素是唯一的,不能包含重复的元素。 -
无序: 存储的元素没有特定的顺序,迭代时的顺序可能与插入顺序不同。
-
快速查找:
HashSet
查找速度较快,平均时间复杂度为 O(1)。 -
允许 null:
HashSet
允许存储一个 null 元素。
用法
import java.util.*; class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } @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 String toString() { return "student{name = " + name + ", age = " + age + "}"; }
} public class javatest { public static void main(String[] args) { Student student = new Student("wjq", 18); Student student1 = new Student("ricci", 18); System.out.println(student.hashCode()); System.out.println(student1.hashCode());//如果没有重写hashcode方法,那么两个对象即使内容相同,哈希值也会不同 Student student2 = new Student("w", 18); Student student3 = new Student("w", 18); System.out.println(student2.hashCode()); System.out.println(student3.hashCode());//重写hashcode方法之后,内容相同的对象哈希值相同 }
}
底层原理
LinkedHashSet
-
有序,存取顺序一致。
-
不允许存储重复的元素。
-
允许 null 值: 可以包含一个 null 元素。
常用方法
add(E e)
: 添加元素。remove(Object o)
: 删除元素。contains(Object o)
: 检查元素是否存在。size()
: 获取集合大小。clear()
: 清空集合。
示例
LinkedHashSet<String> set = new LinkedHashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复元素不会被添加
System.out.println(set); // 输出: [Apple, Banana]
LinkedHashSet
适用于需要保持元素插入顺序且不重复的场合。
TreeSet
- 对数字进行排序
import java.util.Iterator;
import java.util.TreeSet; public class javatest { public static void main(String[] args) { TreeSet<Integer> treeSet = new TreeSet<>(); treeSet.add(5); treeSet.add(2); treeSet.add(8); treeSet.add(1); System.out.println(treeSet);//会进行排序 //几种遍历方式 Iterator<Integer> iterator = treeSet.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } for (Integer i : treeSet) { System.out.println(i); } treeSet.forEach(System.out::println); }
}
两种排序方式
- 实现comparable接口,这是默认的排序方式,基于红黑规则排序
import java.util.TreeSet; class student implements Comparable<student> { private String name; private int age; public student() { } public student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "student{name = " + name + ", age = " + age + "}"; } @Override public int compareTo(student other) { return this.age - other.age;
// this 表示当前要添加的元素
// other 表示已经在红黑树存在的元素
// 返回值:
// 负数:认为要添加的元素是小的,存左边
// 正数:认为要添加的元素是大的,存右边
// 0:认为要添加的元素已经存在,舍弃 }
}
public class javatest { public static void main(String[] args) { student s = new student("wjq", 28); student s1 = new student("gjh", 19); TreeSet<student> set = new TreeSet<>(); set.add(s); set.add(s1); for (student st : set) { System.out.println(st); } }
}
- Comparator排序法
import java.util.Comparator;
import java.util.TreeSet; public class javatest { public static void main(String[] args) { //比较器排序法 TreeSet<String> ts = new TreeSet<>((o1, o2) -> { int i = o1.length() - o2.length(); i = i == 0 ? o1.compareTo(o2) : i;//先按照长度进行排序,如果长度相同就按照默认的排序规则进行排序. // 如果长度不同就按照i的值的正负进行排序 return i; });//简化成lambada表达式 ts.add("c"); ts.add("ab"); ts.add("df"); ts.add("qwer"); System.out.println(ts); }
}