JAVASE进阶day07(泛型,集合,Set,TreeSet,枚举,数据结构,设计模式)
泛型#
1.泛型的基本使用#
限制集合存储的数据类型
package com.lu.day07.generics;
/**
* 定义了一个泛型类
* E 泛型通配字母(不固定代替真实数据类型A-Z都可以)
* 常见的泛型通配字母:
* E:element 元素
* T:type 类型
* R:return 返回值类型
* K:key 键
* v: value 值
* 子类一旦指定泛型父类用的也是子类的泛型
* @param <E>
*/
public class Date<E> {
private E date;
public E getDate() {
return date;
}
public void setDate(E date) {
this.date = date;
}
public static void main(String[] args) {
Date<String> a = new Date<>();
a.setDate("我是你爸爸");
String date = a.getDate();
System.out.println(a.getDate());
Date<Integer> b = new Date<>();
b.setDate(123);
Integer date1 = b.getDate();
System.out.println(date1);
}
}
Set#
1.set集合的概念#
2.HashSet的基本使用 #
package com.lu.day07.setdome;
import java.util.HashSet;
import java.util.Objects;
public class SetDome {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("张三");
set.add("张三");
set.add("王二");
set.add("劳模");
set.add("小李");
System.out.println(set);
//HashSet自定义对象想要去重必须重写 equals 和 hashCode 方法
HashSet<Teacher> t = new HashSet<>();
t.add(new Teacher("张老师","男","教师"));
t.add(new Teacher("张老师","男","教师"));
t.add(new Teacher("王老师","女","幼师"));
t.add(new Teacher("李老师","男","主任"));
System.out.println(t);
//为什么重写 equals 必须重写 hashCode?
//hash(哈希):是由hash算法对任意的输入产生一个整数,并且是固定的
//哈希碰撞:同一个输入产生的hash值永远一样,但是不同的输入生成的hash值可能一样
//hash如果内容一样就生成一样的hash值但是(如果内容相同)hash值可能相同这时候就需要equals进行比较了
//如果两个对象根据 equals 方法认为是相等的,那么它们必须有相同的 hashCode 值。
//如果两个对象 hashCode 值相等,它们未必 equals 相等,但如果 hashCode 不相等,它们一定不相等。
String a = "a";
String b = "b";
System.out.println(Objects.hashCode(a));
System.out.println(Objects.hashCode(b));
}
}
package com.lu.day07.setdome;
import java.util.Objects;
public class Teacher {
private String name;
private String sex;
private String job;
public Teacher() {
}
public Teacher(String name, String sex, String job) {
this.name = name;
this.sex = sex;
this.job = job;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", job='" + job + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Teacher teacher)) return false;
return Objects.equals(getName(), teacher.getName()) && Objects.equals(getSex(), teacher.getSex()) && Objects.equals(getJob(), teacher.getJob());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getSex(), getJob());
}
}
3.TreeSet的基本使用
#
package com.lu.day07.setdome;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
//整数默认升序排序
TreeSet<Integer> set = new TreeSet<>();
set.add(1);
set.add(2);
set.add(8);
set.add(7);
set.add(5);
set.add(2);
System.out.println(set);
//字符串默认按码值进行升序排序
//按照字母顺序比较码值(如果第一个相同就比较第二个)
TreeSet<String> s = new TreeSet<>();
s.add("A");
s.add("E");
s.add("S");
s.add("C");
s.add("G");
System.out.println(s);
}
}
自定义对象排序
package com.lu.day07.setdome;
import java.util.Comparator;
import java.util.TreeSet;
public class Test {
public static void main(String[] args) {
//两种排序方式,构造器传入比较器优先生效
Comparator<Student> c = ((o1,o2)->o2.getAge().compareTo(o1.getAge()));
TreeSet<Student> set = new TreeSet<>(c);
set.add(new Student("希洪",21));
set.add(new Student("dog",23));
set.add(new Student("倒戈",54));
set.add(new Student("马戏",12));
set.add(new Student("傻逼",67));
set.forEach(System.out::println);
}
}
package com.lu.day07.setdome;
import java.util.Objects;
public class Student implements Comparable<Student> {
private String name;
private Integer age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student student)) return false;
return Objects.equals(getName(), student.getName()) && Objects.equals(getAge(), student.getAge());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return age.compareTo(o.getAge());
}
}
4.练习#
package com.lu.day07.test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;
/**
* 有四个学生(姓名,算法成绩,数据结构成绩,英语成绩),按照总分从高到低输出到控制台,
*/
public class Test {
public static void main(String[] args) {
// shift + f6
//shift + f6 + fn
//查找ctrl + F
//替换ctrl + R
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三", 23.0, 56.0, 45.0));
list.add(new Student("李四", 45.0, 54.0, 12.0));
list.add(new Student("王二",21.0,56.0,23.0));
list.add(new Student("六四",78.0,43.0,89.0));
list.sort((o1, o2) -> o2.grade().compareTo(o1.grade()));
list.forEach(System.out::println);
//产生10个1-20之间的随机数,要求随机数不能重复,并且打到控制台
HashSet<Integer> set = new HashSet<>();
Random random = new Random();
while (set.size()<10){
int i = random.nextInt(1, 21);
set.add(i);
}
System.out.println(set);
}
}
package com.lu.day07.test;
public class Student {
private String name;
private double algorithmicScores;
private double dataGrades;
private double englishScores;
public Double grade(){
System.out.println(algorithmicScores+dataGrades+englishScores);
return (algorithmicScores+dataGrades+englishScores);
}
public Student(String name, double algorithmicScores, double dataGrades, double englishScores) {
this.name = name;
this.algorithmicScores = algorithmicScores;
this.dataGrades = dataGrades;
this.englishScores = englishScores;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getAlgorithmicScores() {
return algorithmicScores;
}
public void setAlgorithmicScores(double algorithmicScores) {
this.algorithmicScores = algorithmicScores;
}
public double getDataGrades() {
return dataGrades;
}
public void setDataGrades(double dataGrades) {
this.dataGrades = dataGrades;
}
public double getEnglishScores() {
return englishScores;
}
public void setEnglishScores(double englishScores) {
this.englishScores = englishScores;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", algorithmicScores=" + algorithmicScores +
", dataGrades=" + dataGrades +
", englishScores=" + englishScores +
'}';
}
}
TreeSet相关数据结构#
HashSet只会保存第一次创建对象时的hash值
树#
1.概念#
2.树结构相关概念 #
3.节点对象构成 #
4.常见的树结构 #
枚举#
1.枚举的基本使用#
package com.lu.day07.enmus;
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
package com.lu.day07.enmus;
public class Test {
public static void main(String[] args) {
season(Season.SPRING);
}
public static void season(Season season){
switch (season){
case SPRING -> System.out.println("春天");
case SUMMER -> System.out.println("夏天");
case AUTUMN -> System.out.println("秋天");
case WINTER -> System.out.println("冬天");
}
}
}
package com.lu.day07.enmus;
/**
* 分数等级枚举
* 如果等级范围常量应该使用枚举,
* 枚举提供了一个values静态方法可以遍历所有枚举项,方便逻辑的扩展;
*/
public enum LeveEnum {
BAD(0,60,"差"),
MIDDLE(60,70,"中"),
NOT_BAD(70,80,"良"),
PERFECT(80,100,"优");
private int start;
private int end;
private String name;
LeveEnum(int s,int e,String name){
this.start = s;
this.end = e;
this .name = name;
}
public static void judgeLevel(int c){
LeveEnum[] values = LeveEnum.values();
for (LeveEnum value : values) {
if (c>=value.getStart() && c <= value.getEnd()){
System.out.println(value.getName());
return;
}
}
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.lu.day07.enmus;
public enum Season {
SPRING("春天"){
@Override
public void show() {
System.out.println("春困");
}
},
SUMMER("夏天") {
@Override
public void show() {
System.out.println("夏打盹");
}
}, AUTUMN("秋天") {
@Override
public void show() {
System.out.println("秋眠");
}
}, WINTER("冬天") {
@Override
public void show() {
System.out.println("冬完");
}
};
private String name;
private Season(String name){
this.name = name;
}
public void showName(){
System.out.println(name);
}
public abstract void show();
}
面试题#
1.为什么重写 equals 必须重写 hashCode?#
hash(哈希):是由hash算法对任意的输入产生一个整数,并且是固定的 哈希碰撞:同一个输入产生的hash值永远一样,但是不同的输入生成的hash值可能一样 hash如果内容一样就生成一样的hash值但是(如果内容相同)hash值可能相同,这时候就需要equals进行比较了。 如果两个对象根据 equals 方法认为是相等的,那么它们必须有相同的 hashCode 值。 如果两个对象 hashCode 值相等,它们未必 equals 相等,但如果 hashCode 不相等,它们一定不相等。
2.说出常见的设计模式#
设计模式是在软件开发中解决常见问题的最佳实践和经验总结。它们被广泛应用于提高代码的可重用性、可维护性和可扩展性。常见的设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。以下是每类中的一些常见设计模式:
一、创建型模式
创建型模式主要关注对象的创建过程,它们将对象的创建与使用分离,使得增加新的创建逻辑时不需要修改现有代码。
-
单例模式(Singleton Pattern):确保一个类仅有一个实例,并提供一个全局访问点。常用于配置文件的读取、连接池的管理等场景。
从内存角度来看,该类只有有个对象存在
package com.lu.day15;
import java.util.Objects;
/**
* 单例模式管理员类
* 单例模式书写
* 1.构造器私有
* 2.组合当前类属性
* 3.提供一个静态方法创建对象并返回
*
* 面试题如何创建线程安全的单例模式
*/
public class Admin {//非线程安全的单例模式
public static final String USERNAME = "admin";
public static final String PASSWORD = "123456";
private static Admin admin = new Admin();
private Admin()
{
}
public static Admin getAdmin() {
if (Objects.isNull(admin)) {
admin = new Admin();
}
return admin;
}
}
package com.lu.day15;
public class Test1 {
public static void main(String[] args) {
Admin admin = Admin.getAdmin();
Admin admin1 = Admin.getAdmin();
System.out.println(admin == admin1);//true
}
}
静态的只能写工具类或者服用的方法,方法调用使用单例模式
-
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
-
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
-
建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
package com.lu.day15.pattern;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class Book {
private String bookName;
private String author;
private String publisher;
private double price;
/**
* 字段
*/
private int count;
/**
* 章节
*/
private int chapter;
private String type;
/**
* 出版日期
*/
private LocalDate publishTime;
static class Bulider{
private String bookName;
private String author;
private String publisher;
private double price;
private int count;
private int chapter;
private String type;
private LocalDate publishTime;
public Bulider bookName(String bookName){
this.bookName = bookName;
return this;
}
public Bulider author(String author){
this.author = author;
return this;
}
public Bulider publisher(String publisher){
this.publisher = publisher;
return this;
}
public Bulider price(double price){
this.price = price;
return this;
}
public Bulider count(int count){
this.count = count;
return this;
}
public Bulider chapter(int chapter){
this.chapter = chapter;
return this;
}
public Bulider type(String type){
this.type = type;
return this;
}
public Bulider publishTime(LocalDate publishTime){
this.publishTime = publishTime;
return this;
}
public Book bulid(){
return new Book(this);
}
}
private Book(Bulider bulider){
this.bookName = bulider.bookName;
this.author = bulider.author;
this.publisher = bulider.publisher;
this.price = bulider.price;
this.count = bulider.count;
this.chapter = bulider.chapter;
this.type = bulider.type;
this.publishTime = bulider.publishTime;
System.out.println(LocalDateTime.now());
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", author='" + author + '\'' +
", publisher='" + publisher + '\'' +
", price=" + price +
", count=" + count +
", chapter=" + chapter +
", type='" + type + '\'' +
", publishTime=" + publishTime +
'}';
}
}
package com.lu.day15.pattern;
import java.time.LocalDate;
public class Test {
public static void main(String[] args) {
/*
特点:可以用链式编程
简单建造者模式:
用来创建对象的设计模式
代替复杂的set方法以及有参构造器给属性赋值的
1.类中创建一个静态内部类Builder
2.Builder类的的属性全部都是被建造类的属性
3.给每一个属性提供赋值方法
该方法具备一下特点:方法名与属性名相同
返回值都是Builder对象
4.提供最后构建对象的方法build,该方法返回值是被建造类对象
5.给被构造者类提供私有化构造器,参数是Builder
*/
Book.Bulider bulider = new Book.Bulider();
bulider.author("罗贯中").bookName("三国演义").chapter(100).count(100).price(100).publishTime(LocalDate.now()).publisher("罗贯中").type("小说");
System.out.println(bulider.bulid());
Student.StudentBuilder builder = Student.builder();
builder.address("北京").age(18).email("").name("张三").phone("").sex("男");
System.out.println(builder);
}
}
package com.lu.day15.pattern;
import lombok.Builder;
@Builder
public class Student {
private String name;
private int age;
private String sex;
private String address;
private String phone;
private String email;
}
4.原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。
二、结构型模式
结构型模式关注于类或对象的组合,它们采用继承以外的方式来组合接口或类。
1.适配器模式(Adapter Pattern):将一个类的接口转换成客户端所期待的另一种接口形式,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
2.装饰者模式(Decorator Pattern):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式比生成子类更为灵活。(与继承一样,是为了增强一个类的功能,但是继承是高耦合性的此模式是在不适用继承的前提下,使用组合来增强一个类的功能,被装饰(被增强的)类与增强(装饰类)类具有相同的父类/父接口)也叫可插拔的设计模式
3.代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。
4.外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
5.桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
6.组合模式(Composite Pattern):将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
7.享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度的对象。
三、行为型模式
行为型模式关注对象之间的通信和职责分配。
-
策略模式(Strategy Pattern):定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。(就是用枚举代替很多个复杂的if else语句)
-
模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
-
观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
-
迭代器模式(Iterator Pattern):提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
-
责任链模式(Chain of Responsibility Pattern):为请求的发送者和接收者之间解耦,使多个对象都有机会处理这个请求,从而避免请求的发送者和接收者之间的耦合关系。
-
命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
-
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
-
备忘录模式(Memento Pattern):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
-
访问者模式(Visitor Pattern):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
-
中介者模式(Mediator Pattern):用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
-
解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
这些设计模式是软件开发中经过验证的、有效的解决方案,它们可以帮助开发者设计出更加灵活、可维护和可扩展的软件系统。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix