set集合
1.Set集合概述和特点
总结:
a.Set集合的特点:
1.不允许存储重复的元素
2.没有索引
b.Set集合的基本使用
因为Set集合也是接口所以只能以多态的形式,实现其子类对象
Set<String> set = new HashSet<>();
2.哈希值【理解】
-
总结:
哈希值简介:
a.用于计算存储元素的位置,提高存储元素和取出元素的效效率的。
如何获取哈希值:
a.使用object类中的HashCode()方法。
哈希值的特点
a.同一对象的哈希值是一样的。
b.默认情况下,不同的对象哈希值是不一样的,重写HashCode就能达到不同对象的哈希值是一样的。
3.hashSet集合概述和特点
总结:
HashSet集合的特点:
1.无序(存储顺序和取出的顺序有可能是不一致的)
2.不允许存储重复的元素
3.没有索引(所以不能用普通for循环遍历元素)
数据结构:
JDK8之前:哈希表(数组+链表)
JDK8之后:哈希表(数组+链表+红黑树)
4.Hashset的基本使用
HashSet<String> set = new HashSet<>();
Set.add("abc");
set.add("def");
set.add("egi");
for(String s:set){
Sys.out.println(s);
}
5.HashSet集合保证元素唯一性源码分析
- 首先计算该元素的哈希值(hash()),在哈希表中找有没有相同的哈希值
- 如果没有相同的哈希值,认定为这个元素不是一个重复的元素,添加到哈希表中
- 如果有相同的哈希值,必须再调用equals方法判断相同的哈希表值的内容是否是一样的。
- 如果内容一样:认定为这个元素就是一个重复的元素,不存储
- 如果内容不一样,认定这个元素不是一个重复的元素,存储
结论:
1.要判断一个元素是否是唯一的,必须重写HashCode和equals方法
2.java自己给的类大部分都重写了HashCode和equals方法所以在自己建类时根据要求重写HashCode和equals方法。
HashSet案例:
/** 案例需求
创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
* 要求:学生对象的成员变量值相同,我们就认为是同一个对象
*/
package HashSetDemo01;
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 +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
//测试类
package HashSetDemo01;
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
Student s = new Student("小黑",22);
Student s1 = new Student("小花",24);
Student s2 = new Student("小白",23);
Student s4 = new Student("小白",23);
HashSet<Student> hash = new HashSet<>();
hash.add(s);
hash.add(s1);
hash.add(s2);
hash.add(s4);
for (Student student : hash) {
System.out.println(student);
}
}
}
6.LinkedHashSet集合概述和特点【应用】
LinkedHashSet集合的特点
1.有序(存储顺序和取出顺序是一致的)
2.不允许存储重复的元素
3.没有索引
数据结构:
哈希表 = (数组+链表+链表==>数组+双向链表)
LinkedHashSet集合基本使用
public class LinkedHashSetDemo01 {
public static void main(String[] args) {
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add(new String("重地"));
linkedHashSet.add(new String("通话"));
linkedHashSet.add(new String("cde"));
System.out.println(linkedHashSet);
}
}
7.TreeSet集合概述和特点:
总结:
TreeSet集合的特点:
1.有序(按照一定的规则进行排序,形成一定顺序的数据结构)
2.不允许存储重复的元素
3.没有索引
TreeSet构造方法
1.TreeSet():按照自然顺序排序
2.Tree(Comparator comparator):按照比较器进行比较
案例:
1.自然排序Comparable的使用
* 案例需求
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
* 实现步骤
用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
public class TreeSetDemo02 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();
//创建学生对象
Student s1 = new Student("xishi", 29);
Student s2 = new Student("wangzhaojun", 28);
Student s3 = new Student("diaochan", 30);
Student s4 = new Student("yangyuhuan", 33);
Student s5 = new Student("linqingxia",33);
Student s6 = new Student("linqingxia",33);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历集合
for (Student s : ts) {
System.out.println(s.getName() + "," + s.getAge());
}
}
}
public class Student implements Comparable<Student> {
private String name;
private int age;
@Override
public int compareTo(Student s) {
// return 0; 表示比较的两个对象相等
// return 1; 表示的是按照升序排序
// return -1; 表示的是按照降序排序
//按照年龄从小到大排序
// int num = this.age - s.age;
// 按照年龄从大到小排序
int num = s.age - this.age; // 主要条件
// s.name.length() - this.name.length();
// s.name.charAt(0) - this.name.charAt(0);
//年龄相同时,按照姓名的字母顺序排序
// 次要条件
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
}
2.10 比较器排序Comparator的使用
/* 案例需求
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
* 实现步骤
用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
案例代码:*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象
// 先定义一个Comparator实现类 重写compare方法,在创建TreeSet的时候,将omparator实现类的对象给这个构造
TreeSet<Student> ts = new TreeSet<Student>(new ComparatorImpl());
//创建学生对象
Student s1 = new Student("xishi", 29);
Student s2 = new Student("wangzhaojun", 28);
Student s3 = new Student("diaochan", 30);
Student s4 = new Student("yangyuhuan", 33);
Student s5 = new Student("linqingxia",33);
Student s6 = new Student("linqingxia",33);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历集合
for (Student s : ts) {
System.out.println(s.getName() + "," + s.getAge());
}
}
}
class ComparatorImpl implements Comparator<Student>{
public int compare(Student s1, Student s2) {
//this.age - s.age
//s1,s2 s1 - s2 按照升序进行排序 s2 - s1 : 按照降序进行排序
int num = s1.getAge() - s2.getAge();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
}
public class Student {
private String name;
private int age;
}
3.综合排序
/* 案例需求
* 用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
* 要求:按照总分从高到低出现*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建TreeSet集合对象,通过比较器排序进行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// int num = (s2.getChinese()+s2.getMath())-(s1.getChinese()+s1.getMath());
//主要条件 按照总成绩的降序排序
int num = s2.getSum() - s1.getSum();
//次要条件 如果总成绩相等 就按照语文成绩进行排序 按照语文的升序进行排序
int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
// 如果是总成绩一样 语文成绩也一样就按照名字进行排序 ,按照自然顺序进行排序
int num3 = num2 == 0 ? s1.getName().compareTo(s2.getName()) : num2;
return num3;
}
});
//创建学生对象
Student s1 = new Student("林青霞", 98, 100);
Student s2 = new Student("张曼玉", 95, 95);
Student s3 = new Student("王祖贤", 100, 93);
Student s4 = new Student("柳岩", 100, 97);
Student s5 = new Student("风清扬", 98, 98);
Student s6 = new Student("左冷禅", 97, 99);
// Student s7 = new Student("左冷禅", 97, 99);
Student s7 = new Student("赵云", 97, 99);
//把学生对象添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
//遍历集合
for (Student s : ts) {
System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getSum());
}
}
}
public class Student {
private String name;
private int chinese;
private int math;
public Student() {
}
public Student(String name, int chinese, int math) {
this.name = name;
this.chinese = chinese;
this.math = math;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getSum() {
return this.chinese + this.math;
}
}