Set集合
- HashSet (哈希表) 唯一,无序;添加、删除、查询速度快
- LinkedHashSet (哈希表+链表) 唯一,有序(添加顺序);比哈希表慢点
- TreeSet 红黑树(一种二叉平衡树)唯一,有序(自然顺序);查询速度(按内容查)比List快,没HashSet 哈希表快
- List针对Collection增加了一些对索引的操作方法,如add(1),remove(1),get(1),set(1,"A")
- Set是无序的,不能增加对索引操纵的方法,Set针对Collection没有增加任何方法
- List的遍历方式:for循环,for-each循环,Iterator迭代器,流式编程forEach
- Set的遍历方式:for-each循环,Iterator迭代器,流式编程forEach
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo01 {
public static void main(String[] args) {
Set<String> set = new TreeSet();
set.add("JavaSE");
set.add("JavaEE");
set.add("MySql");
set.add("Html");
set.add("JavaSE");
System.out.println(set);//[Html, JavaEE, JavaSE, MySql] 唯一,自然顺序
System.out.println(set.size());// 4
System.out.println("=============遍历方法一:for-each=============");
for (String elem : set) {
System.out.println(elem);
}
System.out.println("=============遍历方法二:迭代=============");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
System.out.println("=============遍历方法三:拉姆达表达式+流式编程=============");
set.forEach(item -> System.out.println(item));
}
}
执行结果:
[Html, JavaEE, JavaSE, MySql]
4
=============遍历方法一:for-each=============
Html
JavaEE
JavaSE
MySql
=============遍历方法二:迭代=============
Html
JavaEE
JavaSE
MySql
=============遍历方法三:拉姆达表达式+流式编程=============
Html
JavaEE
JavaSE
MySql
Process finished with exit code 0
1.创建一个学生类存到Set中
1.1先创建Student类
package com.zhang.setdemo;
public class 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 +
'}';
}
}
1.2.创建测试类
package com.zhang.setdemo;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo01 {
public static void main(String[] args) {
Set<Student> set = new HashSet();
Student stu1 = new Student("zhangsan", 20);
Student stu2 = new Student("lisi", 23);
Student stu3 = new Student("wangwu", 23);
Student stu4 = new Student("zhangsan", 20);
set.add(stu1);
set.add(stu2);
set.add(stu3);
set.add(stu4);
System.out.println(set);
//[Student{name='wangwu', age=23}, Student{name='lisi', age=23}, Student{name='zhangsan', age=20}, Student{name='zhangsan', age=20}]
Set<Student> set2 = new LinkedHashSet();
Student stu11 = new Student("zhangsan", 20);
Student stu22 = new Student("lisi", 23);
Student stu33 = new Student("wangwu", 23);
Student stu44 = new Student("zhangsan", 20);
set2.add(stu11);
set2.add(stu22);
set2.add(stu33);
set2.add(stu44);
System.out.println(set2);
//[Student{name='zhangsan', age=20}, Student{name='lisi', age=23}, Student{name='wangwu', age=23}, Student{name='zhangsan', age=20}]
Set<Student> set3 = new TreeSet();
Student stu111 = new Student("zhangsan", 20);
Student stu222 = new Student("lisi", 23);
Student stu333 = new Student("wangwu", 23);
Student stu444 = new Student("zhangsan", 20);
set3.add(stu111);
set3.add(stu222);
set3.add(stu333);
set3.add(stu444);
System.out.println(set3);//java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable
}
}
运行发现
- 问题1.HashSet和LinkedHashSet存储String是唯一的,但是存储Student不唯一
- 问题2.TreeSet存储String是有序的,但是存储Student报异常:java.lang.ClassCastException: Student cannot be cast to java.lang.Comparable
解决方法:
- 问题1解决方法
1.在Student类重写equals和hashCode,缺一不可
@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);
}
再次运行发现:HashSet和LinkedHashSet的结果唯一。
HashSet的结果:[Student{name='lisi', age=23}, Student{name='zhangsan', age=20}, Student{name='wangwu', age=23}]
LinkedHashSet的结果:[Student{name='zhangsan', age=20}, Student{name='lisi', age=23}, Student{name='wangwu', age=23}]
- 问题2解决方法
方法1:Student类实现Comparable接口,重写compareTo方法
public class Student implements Comparable<Student> {
@Override
public int compareTo(Student other) {
return this.name.compareTo(other.name);
}
}
运行结果:
HashSet的结果:
[Student{name='lisi', age=23}, Student{name='zhangsan', age=20}, Student{name='wangwu', age=23}]
LinkedHashSet的结果:
[Student{name='zhangsan', age=20}, Student{name='lisi', age=23}, Student{name='wangwu', age=23}]
TreeSet的结果:
[Student{name='lisi', age=23}, Student{name='wangwu', age=23}, Student{name='zhangsan', age=20}]
Process finished with exit code 0
方法2:自定义外部比较器
有自定义的外部比较器以外部比较器为准,没有外部比较器的走内部比较器
按年龄升序,姓名降序排列
方法三:匿名内部类
package com.zhang.setdemo;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo03 {
public static void main(String[] args) {
//匿名内部类,年龄升序,姓名升序
Comparator com = new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {
if (stu1.getAge() < stu2.getAge()) {
return -1;
} else if (stu1.getAge() > stu2.getAge()) {
return 1;
} else {
return stu1.getName().compareTo(stu2.getName());
}
}
};
Set<Student> set3 = new TreeSet(com);
Student stu111 = new Student("zhangsan", 20);
Student stu222 = new Student("lisi", 23);
Student stu333 = new Student("wangwu", 23);
Student stu444 = new Student("zhangsan", 20);
set3.add(stu111);
set3.add(stu222);
set3.add(stu333);
set3.add(stu444);
System.out.println(set3);
}
}
执行结果:
[Student{name='zhangsan', age=20}, Student{name='lisi', age=23}, Student{name='wangwu', age=23}]
Process finished with exit code 0
方法四:拉姆达表达式
package com.zhang.setdemo;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo04 {
public static void main(String[] args) {
//拉姆达表达式
Set<Student> set3 = new TreeSet<Student>((Student stu1, Student stu2) -> {
if (stu1.getAge() < stu2.getAge()) {
return -1;
} else if (stu1.getAge() > stu2.getAge()) {
return 1;
} else {
return stu1.getName().compareTo(stu2.getName());
}
});
Student stu111 = new Student("zhangsan", 20);
Student stu222 = new Student("lisi", 23);
Student stu333 = new Student("wangwu", 23);
Student stu444 = new Student("zhangsan", 20);
set3.add(stu111);
set3.add(stu222);
set3.add(stu333);
set3.add(stu444);
System.out.println(set3);
}
}
方法五:拉姆达表达式一条语句的用法
package com.zhang.setdemo;
import java.util.Set;
import java.util.TreeSet;
public class SetDemo05 {
public static void main(String[] args) {
//拉姆达表达式
Set<Student> set3 = new TreeSet<Student>((stu1, stu2) -> stu1.getName().compareTo(stu2.getName()));
Student stu111 = new Student("zhangsan", 20);
Student stu222 = new Student("lisi", 23);
Student stu333 = new Student("wangwu", 23);
Student stu444 = new Student("zhangsan", 20);
set3.add(stu111);
set3.add(stu222);
set3.add(stu333);
set3.add(stu444);
System.out.println(set3);
}
}
执行结果:
[Student{name='lisi', age=23}, Student{name='wangwu', age=23}, Student{name='zhangsan', age=20}]
Process finished with exit code 0