Set接口讲解
一、HashSet实现类的使用
1、放入Integer类型数据
package com.lanson.test07;
import java.util.HashSet;
/**
* @author : lansonli
*/
public class TestInteger {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个HashSet集合:
HashSet<Integer> hs = new HashSet<>();
System.out.println(hs.add(19));//true
hs.add(5);
hs.add(20);
System.out.println(hs.add(19));//false 这个19没有放入到集合中
hs.add(41);
hs.add(0);
System.out.println(hs.size());//唯一,无序
System.out.println(hs);
}
}
2、放入String类型数据
package com.lanson.test07;
import java.util.HashSet;
/**
* @author : lanson
*/
public class TestString {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个HashSet集合:
HashSet<String> hs = new HashSet<>();
hs.add("hello");
hs.add("apple");
hs.add("banana");
hs.add("html");
hs.add("apple");
hs.add("css");
System.out.println(hs.size());
System.out.println(hs);
}
}
3、放入自定义的引用数据类型的数据
package com.lanson.test07;
import java.util.HashSet;
/**
* @author : lansonli
*/
public class TestStudent {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个HashSet集合:
HashSet<Student> hs = new HashSet<>();
hs.add(new Student(19,"lili"));
hs.add(new Student(20,"lulu"));
hs.add(new Student(18,"feifei"));
hs.add(new Student(19,"lili"));
hs.add(new Student(10,"nana"));
System.out.println(hs.size());
System.out.println(hs);
}
}
上面自定义的类型不满足 唯一,无序的特点。为什么呢?
4、HashSet原理图:(简要原理图)
5、疑问
5.1、数组的长度是多少?
5.2、数组的类型是什么?
5.3、hashCode,equals方法真的调用了吗?
5.4、底层表达式是什么?
5.5、同一个位置的数据向前放还是向后放?
5.6、放入数组中的数据,是直接放的吗?是否封装为对象了?
二、LinkedHashSet使用
其实就是在HashSet的基础上,多了一个总的链表,这个总链表将放入的元素串在一起,方便有序的遍历:
可以看到LinkedHashMap.Entry 继承自HashMap.Node 除了Node 本身有的几个属性外,额外增加了before after 用于指向前一个Entry 后一个Entry。也就是说,元素之间维持着一条总的链表数据结构
代码:
package com.lanson.test07;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
/**
* @author : lansonli
*/
public class TestInteger {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个HashSet集合:
LinkedHashSet<Integer> hs = new LinkedHashSet<>();
System.out.println(hs.add(19));//true
hs.add(5);
hs.add(20);
System.out.println(hs.add(19));//false 这个19没有放入到集合中
hs.add(41);
hs.add(0);
System.out.println(hs.size());//唯一,无序
System.out.println(hs);
}
}
三、比较器的使用
1、以int类型为案例
比较的思路:将比较的数据做差,然后返回一个int类型的数据,将这个int类型的数值 按照 =0 >0 <0
int a = 10;
int b = 20;
System.out.println(a-b); // =0 >0 <0
2、比较String类型数据
String类实现了Comparable接口,这个接口中有一个抽象方法compareTo,String类中重写这个方法即可
String a = "A";
String b = "B";
System.out.println(a.compareTo(b));
3、比较double类型数据
double a = 9.6;
double b = 9.3;
/* System.out.println((int)(a-b));*/
System.out.println(((Double) a).compareTo((Double) b));
4、比较自定义的数据类型
4.1、内部比较器
package com.lanson.test08;
/**
* @author : lansonli
*/
public class Student implements Comparable<Student>{
private int age;
private double height;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, double height, String name) {
this.age = age;
this.height = height;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", height=" + height +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
//按照年龄进行比较:
/*return this.getAge() - o.getAge();*/
//按照身高比较
/*return ((Double)(this.getHeight())).compareTo((Double)(o.getHeight()));*/
//按照名字比较:
return this.getName().compareTo(o.getName());
}
}
package com.lanson.test08;
/**
* @author : lansonli
*/
public class Test02 {
//这是main方法,程序的入口
public static void main(String[] args) {
//比较两个学生:
Student s1 = new Student(14,160.5,"alili");
Student s2 = new Student(14,170.5,"bnana");
System.out.println(s1.compareTo(s2));
}
}
4.2、外部比较器
package com.lanson.test09;
import java.util.Comparator;
/**
* @author : lansonli
*/
public class Student{
private int age;
private double height;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, double height, String name) {
this.age = age;
this.height = height;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", height=" + height +
", name='" + name + '\'' +
'}';
}
}
class BiJiao01 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//比较年龄:
return o1.getAge()-o2.getAge();
}
}
class BiJiao02 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//比较姓名:
return o1.getName().compareTo(o2.getName());
}
}
class BiJiao03 implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
//在年龄相同的情况下 比较身高 年龄不同比较年龄
if((o1.getAge()-o2.getAge())==0){
return ((Double)(o1.getHeight())).compareTo((Double)(o2.getHeight()));
}else{//年龄不一样
return o1.getAge()-o2.getAge();
}
}
}
package com.lanson.test09;
import com.lanson.test09.Student;
import java.util.Comparator;
/**
* @author : lansonli
*/
public class Test02 {
//这是main方法,程序的入口
public static void main(String[] args) {
//比较两个学生:
Student s1 = new Student(9,160.5,"alili");
Student s2 = new Student(14,170.5,"bnana");
//获取外部比较器:
Comparator bj1 = new BiJiao03();
System.out.println(bj1.compare(s1, s2));
}
}
5、外部比较器和内部比较器谁好呀?
答案:外部比较器,多态,扩展性好
四、TreeSet实现类的使用
1、存入Integer类型数据(底层利用的是内部比较器)
package com.lanson.test10;
import java.util.TreeSet;
/**
* @author : lansonli
*/
public class Test01 {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
TreeSet<Integer> ts = new TreeSet<>();
ts.add(12);
ts.add(3);
ts.add(7);
ts.add(9);
ts.add(3);
ts.add(16);
System.out.println(ts.size());
System.out.println(ts);
}
}
特点:唯一,无序(没有按照输入顺序进行输出), 有序(按照升序进行遍历)
2、原理底层:二叉树(数据结构中的一个逻辑结构)
3、 放入String类型数据:(底层实现类内部比较器)
package com.lanson.test10;
import java.util.TreeSet;
/**
* @author : lansonli
*/
public class Test02 {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
TreeSet<String> ts = new TreeSet<>();
ts.add("elili");
ts.add("blili");
ts.add("alili");
ts.add("elili");
ts.add("clili");
ts.add("flili");
ts.add("glili");
System.out.println(ts.size());
System.out.println(ts);
}
}
4、想放入自定义的Student类型的数据
4.1、利用内部比较器
package com.lanson.test10;
/**
* @author : lansonli
*/
public class Student implements Comparable<Student> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Student o) {
return this.getAge()-o.getAge();
}
}
package com.lanson.test10;
import java.util.TreeSet;
/**
* @author : lansonli
*/
public class Test03 {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
TreeSet<Student> ts = new TreeSet<>();
ts.add(new Student(10,"elili"));
ts.add(new Student(8,"blili"));
ts.add(new Student(4,"alili"));
ts.add(new Student(9,"elili"));
ts.add(new Student(10,"flili"));
ts.add(new Student(1,"dlili"));
System.out.println(ts.size());
System.out.println(ts);
}
}
4.2、通过外部比较器
package com.lanson.test10;
import java.util.Comparator;
/**
* @author : lansonli
*/
public class Student {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
class BiJiao implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
}
package com.lanson.test10;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @author : lansonli
*/
public class Test03 {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
//利用外部比较器,必须自己制定:
Comparator<Student> com = new BiJiao();
TreeSet<Student> ts = new TreeSet<>(com);//一旦指定外部比较器,那么就会按照外部比较器来比较
ts.add(new Student(10,"elili"));
ts.add(new Student(8,"blili"));
ts.add(new Student(4,"alili"));
ts.add(new Student(9,"elili"));
ts.add(new Student(10,"flili"));
ts.add(new Student(1,"dlili"));
System.out.println(ts.size());
System.out.println(ts);
}
}
实际开发中利用外部比较器多,因为扩展性好(多态)
换一种写法:
package com.lanson.test10;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @author : lansonli
*/
public class Test03 {
//这是main方法,程序的入口
public static void main(String[] args) {
//创建一个TreeSet:
//利用外部比较器,必须自己制定:
/*Comparator<Student> com = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
};*/
TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
});//一旦指定外部比较器,那么就会按照外部比较器来比较
ts.add(new Student(10,"elili"));
ts.add(new Student(8,"blili"));
ts.add(new Student(4,"alili"));
ts.add(new Student(9,"elili"));
ts.add(new Student(10,"flili"));
ts.add(new Student(1,"dlili"));
System.out.println(ts.size());
System.out.println(ts);
}
}
5、TreeSet底层的二叉树的遍历是按照升序的结果出现的,这个升序是靠中序遍历得到的
五、Collection部分整体结构图
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨