Set 接口基本介绍
Set接口是Collection接口的一个子接口,其主要特点如下:
- 不允许重复元素:Set接口的实现类不会包含重复的元素。更正式地说,不包含任何一对使得e1.equals(e2)成立的元素e1和e2,并且最多只能有一个null元素。当尝试添加重复元素时,添加操作将被忽略。
- 无序性:Set接口取出元素的顺序和添加元素的顺序不一致(但是每次取出的顺序是固定的),即无法通过索引访问Set中的元素。
Set接口的常用实现类有HashSet、TreeSet和LinkedHashSet。可以使用迭代器和增强 for 循环遍历元素,但是不能使用普通 for 循环(不能使用索引)。下面的代码以其实现类HashSet演示Set接口的特点。- public class TestSet() {
- public static void main(String[] args) {
- Set set = new HashSet();
- set.add("Phoebe");
- set.add("Monica");
- set.add("Phoebe"); // 重复
- set.add("Ross");
- set.add("Chandler");
- set.add("Rachel");
- set.add(null);
- set.add(null); // 再次添加 null
- // 10 次输出结果均为:set=[Phoebe, null, Rachel, Ross, Chandler, Monica]
- // 重复的 Phoebe 和 null 都只输出了一个,
- // 取出顺序和添加顺序不一致但每次取出顺序都是相同的。
- for (int i = 0; i < 10; i++) {
- System.out.println("set=" + set);
- }
- }
- }
复制代码 注意:如果Set集合的元素是可变对象时,必须要小心。如果以影响equals()方法比较结果的方式修改Set中的元素的值,集合的行为是未指定的。这种情况的特例是Set不能将自身作为元素。以下以一个简单的 Person 类来测试修改HashSet中元素的值使得两个元素equals()方法比较结果相同时的情况。- public class Person {
- private String name;
-
- public Person() {
- }
- public Person(String name) {
- this.name = name;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Person person = (Person) o;
- return name.equals(person.name);
- }
- @Override
- public int hashCode() {
- return Objects.hash(name);
- }
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- '}';
- }
- }
复制代码- public class TestModifyValue() {
- public static void main(String[] args) {
- Set set = new HashSet();
-
- // 创建 3 个 Person 实例,其中 rose1.equals(rose2) 成立
- Person jack = new Person("Jack");
- Person rose1 = new Person("Rose");
- Person rose2 = new Person("Rose");
- // 将其添加到 set 中
- set.add(jack);
- set.add(rose1);
- set.add(rose2);
-
- // 可以看到只添加成功一个姓名为 Rose 的 Person 实例,其应为 rose1。
- System.out.println("set = " + set); // set = [Person{name='Rose'}, Person{name='Jack'}]
- // 将 set 添加到自身中,未添加成功
- set.addAll(set);
- System.out.println("set = " + set); // set = [Person{name='Rose'}, Person{name='Jack'}]
- // 将 rose1 的 name 属性修改为 Jack
- rose1.setName("Jack");
- System.out.println(rose1.equals(jack)); // true
- // 可以看到此时 set 集合中仍有两个对象,其 equals() 方法比较结果相同。
- System.out.println("set = " + set); // set = [Person{name='Jack'}, Person{name='Jack'}]
- }
- }
复制代码 Set 接口常用方法
Set接口和List接口一样,也是Collection接口的子接口,因此常用方法和Collection接口一样。但需要注意由于Set接口不包含重复元素,所以addAll()方法的参数也是Set时,addAll操作会有效地修改该集合,使其值为两个集合的并集。- public class SetAddAll() {
- public static void main(String[] args) {
- Set set = new HashSet();
- set.add("Phoebe");
- set.add("Monica");
- set.add("Ross");
- System.out.println("set = " + set); // set = [Phoebe, Ross, Monica]
- Set set1 = new HashSet();
- set1.add("Phoebe");
- set.add("Chandler");
- set.addAll(set1);
- System.out.println("set = " + set); // set = [Phoebe, Ross, Chandler, Monica]
- }
- }
复制代码 Set 接口遍历元素方式
Set接口遍历元素的方式和Collection接口的一样,可以使用迭代器和增强 for 循环来遍历元素,但不能通过索引的方式来遍历元素。- public class SetThroughElements() {
- public static void main(String[] args) {
- Set set = new HashSet();
- set.add("Phoebe");
- set.add("Monica");
- set.add("John");
- System.out.println("---使用迭代器---");
- Iterator iterator = set.iterator();
- while (iterator.hasNext()) {
- Object obj = iterator.next();
- System.out.println("obj = " + obj);
- }
- System.out.println("---使用增强 for---");
- for (Object o :set) {
- System.out.println("o = " + o);
- }
- // 不能使用普通 for 循环,因为 Set 不支持索引
- }
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |