Set集合
Set集合存储特点:无序、不可重复。
无序是指存储顺序与添加顺序可能不一样;不允许存储重复的数据;
相应Api用法可参考Collection集合 - 鹿先森JIAN - 博客园 (cnblogs.com)
下面分别介绍 HashSet、LinkedHashSet、TreeSet 的用法。
查看 HashSet 源码发现在 HashSet 的无参构造方法中创建了 HashMap 集合, 所以 HashSet 底层是 HashMap。
import java.util.HashSet; import java.util.Iterator; import java.util.Set; // Set集合 特点:无序,不重复 public class SetTest { public static void main(String[] args) { Set<String> set = new HashSet<>(); set.add("abcde"); set.add("123"); set.add("123"); // 添加重复数据,加不了滴! set.add("hello"); set.add("xx"); //打印结果跟添加顺序不一样(即无序) System.out.println(set); // [xx, 123, abcde, hello] System.out.println(set.size()); // 4 // 删除指定元素 set.remove("xx"); // 迭代 Iterator<String> iterator = set.iterator(); while (iterator.hasNext()){ String s = iterator.next(); System.out.print(s+"\t"); } // 123 abcde hello /* // foreach 习惯用于无索引的数据输出 for (String i:set ) { System.out.print(i+"\t"); } */ } }
HashSet如果存储自定义类型对象,contains(o)、remove(o) 方法会调用对象的 equals()方法。
在自定义类型中需要重写 equals()、hashCode();所有带 Hash 字样的集合都需要用到哈希码。
// 自定义一个 Student 类 import java.util.Objects; public class Student { private String name; private int age; // 提供 getter、setter方法、无参有参构造 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; } public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } // Alt+insert,重写 toString、equals、hashCode 方法 @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", 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); } }
import java.util.HashSet; // 测试类 public class SetTest01 { public static void main(String[] args) { Student s1 = new Student("zs", 18); Student s2 = new Student("zs", 18); // 存储自定义类型对象 HashSet<Student> students = new HashSet<>(); students.add(s1); students.add(s2); System.out.println(students); // [Student{name='zs', age=18}] /* 虽然s1,s2的地址值不同,但是s1,s2的内容是一样的。 * Student类重写了 equals()、hashCode()方法,就是拿来比较内容的; * 内容一样就不会再被放进去了 * */ } }
----------------------------------------------------------
LinkedHashSet<E> 继承了 HashSet<E>,具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。换句话说,LinkedHashSet 也是无序存储不重复元素的,但是它的打印结果可以跟添加顺序一样!
import java.util.LinkedHashSet; public class SetTest06 { public static void main(String[] args) { LinkedHashSet<String> hashSet = new LinkedHashSet<>(); hashSet.add("hello"); hashSet.add("java"); hashSet.add("java"); hashSet.add("world"); System.out.println(hashSet); // [hello, java, world] } }
----------------------------------------------------
TreeSet实现了SortedSet接口, 可以对集合中的元素自然排序, 要求集合中的元素必须可比较大小。