Set
–HashSet 使用散列函数实现,极大的提高了访问速度。存入HashSet的对象必须定义hashCode()
–LinkedHashSet 使用了链表来保持插入顺序,不过为了提高查询效率,也使用了散列。
–TreeSet 使用红黑树来实现, 时刻维持有序,平衡.
Set方法比List方法少一点
示例代码1
import java.util.*;
public class TestSet {
public static void main(String[] args) {
//以下三种方式都可以得到一个set。输出也是一样的,只不过底层实现不同
Set<String> set = new HashSet<>();
// Set<String> set = new LinkedHashSet<>();
// Set<String> set = new TreeSet<>();
set.add("java");
set.add("Oracle");
set.add("HTML");
set.add("java");
System.out.println(set.size());
System.out.println(set);
// foreach 循环遍历
// for (String elem:set) {
// System.out.println(elem);
//
// }
//因为set没有定义set方法和get方法,所以不能直接用for循环遍历
//Iterator迭代器遍历
Iterator<String> it = set.iterator();
while (it.hasNext()){
String elem = it.next();
System.out.println(elem);
}
}
}
示例代码2
import java.util.HashSet;
import java.util.Set;
public class TestSet2 {
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
Student stu1 = new Student(1, "张三", 15, 87);
Student stu2 = new Student(2, "李四", 16, 88);
Student stu3 = new Student(3, "王五", 14, 65);
Student stu4 = new Student(4, "赵六", 19, 83);
Student stu5 = new Student(1, "张三", 15, 87);
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
set.add(stu5);
System.out.println(set.size());
for (Student s: set) {
System.out.println(s);
}
}
}
其中 Student 类:
有四个成员变量,实现了set和get方法,并实现了构造方法(有参和无参),还实现了toString方法.
示例代码3
public class Student {
private int sno;
private String name;
private int age;
private double score;
public Student(int sno, String name, int age, double score) {
this.sno = sno;
this.name = name;
this.age = age;
this.score = score;
}
public Student() {
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
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 double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"sno=" + sno +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
上面代码执行的结果是
5
Student{sno=1, name='张三', age=15, score=87.0}
Student{sno=1, name='张三', age=15, score=87.0}
Student{sno=4, name='赵六', age=19, score=83.0}
Student{sno=3, name='王五', age=14, score=65.0}
Student{sno=2, name='李四', age=16, score=88.0}
可以发现此时HashSet存储Student类的时候并没有实现不重复的功能,第一条跟第二条内容完全一样,但是却都在HashSet里面.这与实际要求情况不符.
解决方法:
重写 Student 类的equals() 和 hashCode() 方法
这个也可以用IDE自动生成.也可以参考另一篇博客详细讲解如何重写.
示例代码4
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return sno == student.sno &&
age == student.age &&
Double.compare(student.score, score) == 0 &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(sno, name, age, score);
}
此时再次执行TestSet2,发现成功了:
4
Student{sno=4, name='赵六', age=19, score=83.0}
Student{sno=3, name='王五', age=14, score=65.0}
Student{sno=2, name='李四', age=16, score=88.0}
Student{sno=1, name='张三', age=15, score=87.0}
这里自动生成的是按照学号从大到小排序.
重要
·将元素放入到hashSet和LinkedHashSet等底层结构是哈希表的集合中时,需要重写 equals 和 hashCode方法.
·将元素放入TreeSet等底层结构是二叉排序树的集合中时,需要实现Comparable接口或Comparator接口
TreeSet 底层是 TreeMap
Comparator 外部比较器(优先)
comparable 内部比较器 该类对外提供一个默认比较的实现
最终的Student类代码如下:
示例代码5
import java.util.Objects;
public class Student implements Comparable<Student>{
private int sno;
private String name;
private int age;
private double score;
public Student(int sno, String name, int age, double score) {
this.sno = sno;
this.name = name;
this.age = age;
this.score = score;
}
public Student() {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return sno == student.sno &&
age == student.age &&
Double.compare(student.score, score) == 0 &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(sno, name, age, score);
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
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 double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"sno=" + sno +
", name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
@Override
public int compareTo(Student other) {
return this.sno - other.sno;
}
}
另两个执行代码就不展示了,与示例代码二类似.