多态
多态 同类型的对象执行同一个行为会表现出不同行为特征
多态的常见形式:
父类类型 对象名称 = new 子类构造器;
接口 对象名称 = new 实现类构造器;
多态中成员访问的特点:
方法调用:编译看左边 运行看右边
变量调用:编译看左边 运行看左边
package com.itjiaming.polymorphic_d1; import java.util.SplittableRandom; public class Test { public static void main(String[] args) { // 多态的形式 Animal a = new Dog(); a.run(); // 方法调用:编译看左边 运行看右边 System.out.println(a.name); // 编译看左边 运行看左边 // 父类动物 Animal a1 = new Cat(); a1.run(); System.out.println(a1.name); // 父类动物 } } abstract class Animal{ public String name = "父类动物"; public abstract void run(); } class Dog extends Animal{ public String name = "子类狗"; @Override public void run() { System.out.println("狗跑的快==="); } } class Cat extends Animal{ public String name = "子类猫"; @Override public void run(){ System.out.println("猫跑的没有狗快==="); } }
使用前提:有继承、实现关系 有父类引用指向子类对象 有方法重写
多态下不能访问子类的独有功能
多态下引用数据类型的类型转换
自动类型转换(从子到父):子类对象赋值给父类类型的变量指向
强制类型转换(从父到子): 子类 对象变量 = (子类)父类类型的变量
作用 实现子类独有的功能
package com.itjiaming.polymorphic_d1.canvert_d1; public class Test { public static void main(String[] args) { // 自动类型转换 Animal a = new Dog(); a.run(); Animal a1 = new Cat(); a1.run(); // 强制类型准换 Dog d = (Dog) a; d.kanMen(); Cat d1 = (Cat) a1; d1.run(); d1.xiaDan(); } } class Animal{ public void run(){ System.out.println("动物可以跑"); } } class Dog extends Animal{ @Override public void run(){ System.out.println("狗可以跑"); } public void kanMen(){ System.out.println("狗可以看门"); } } class Cat extends Animal{ @Override public void run() { System.out.println("猫可以跑"); } public void xiaDan(){ System.out.println("猫可以下蛋"); } }
注意:
package com.itjiaming.polymorphic_d1.canvert_d1; public class Test { public static void main(String[] args) { // 自动类型转换 Animal a = new Dog(); a.run(); Animal a1 = new Cat(); a1.run(); // 强制类型准换 Dog d = (Dog) a; d.kanMen(); Cat d1 = (Cat) a1; d1.run(); d1.xiaDan(); System.out.println("================"); // 防止报异常 if (a instanceof Dog){ Dog dog = (Dog) a; dog.kanMen(); }else if (a instanceof Cat){ Cat cat = new Cat(); cat.xiaDan(); } } } class Animal{ public void run(){ System.out.println("动物可以跑"); } } class Dog extends Animal{ @Override public void run(){ System.out.println("狗可以跑"); } public void kanMen(){ System.out.println("狗可以看门"); } } class Cat extends Animal{ @Override public void run() { System.out.println("猫可以跑"); } public void xiaDan(){ System.out.println("猫可以下蛋"); } }
内部类
定义在一个类里面的类,里面的类可以理解成寄生,外部类可以理解成宿主
public class People{
// 内部类
public class Heart{}
}
// 静态内部来 public class TEst { public static void main(String[] args) { // 创建对象的方法 Outer.Inner in = new Outer.Inner(); in.setName("涨三"); in.show(); } } class Outer{ public static int a = 100; // 静态成员内部类 public static class Inner{ private String name; public static String schoolName; public Inner() { } public Inner(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 自定义方法 public void show(){ System.out.println(name + "ds "); System.out.println(a); } } }
package com.itjiaming.polymorphic_d1.innerclass_D2; // 成员内部类 public class Test { public static void main(String[] args) { // 创建对象格式 Outer.Inner in = new Outer().new Inner("Sdad",45); in.test(); } } class Outer{ // 成员内部类 不能加static修饰 class Inner{ private String name; private int age; // public static int a; // JDK16 开始支持 public void test(){ System.out.println("ds"); } 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 Inner(String name, int age) { this.name = name; this.age = age; } } }
匿名内部类
本质上是一个没有名字的局部内部类 ,定义在方法中,代码块中
作用: 方便创建子类对像 最终目的是为了简化代码的编写
格式:
new 类|抽象类名|或接口名(){方法重写};
package com.itjiaming.nimingneibulei.d1; public class Test { public static void main(String[] args) { // Animal a = new Tiger(); // a.run(); // 匿名内部类 Animal a = new Animal() { @Override public void run() { System.out.println("老虎跑的快"); } }; a.run(); } } //class Tiger extends Animal{ // @Override // public void run() { // System.out.println("老虎跑的快"); // } //} // 抽象类 不能构建对象 abstract class Animal{ public abstract void run(); }
匿名内部类是一个没有名字的内部类 写出来就会产生一个匿名内部类的对象 匿名内部类的对象类型相当于是当前new的那个的类型的子类类型
作用 方便创建子类的对象 最终简化代码
package com.itjiaming.nimingneibulei.d1; /** * 匿名内部类 */ public class Test2 { public static void main(String[] args) { Swimming s = new Swimming() { @Override public void swim() { System.out.println("学生在游泳‘’‘’‘’‘’"); } }; go(s); Swimming ss = new Swimming() { @Override public void swim() { System.out.println("老师在游泳‘’‘’‘’‘’"); } }; go(ss); go(new Swimming() { @Override public void swim() { System.out.println("运动员在游泳‘’‘’‘’‘’"); } }); } public static void go(Swimming swimming){ System.out.println("开始i====="); swimming.swim(); System.out.println("结束i====="); } } // 定义接口 表示游泳 interface Swimming{ // 游泳方法 void swim(); }
package com.itjiaming.nimingneibulei.d1; import javax.swing.*; import java.awt.event.ActionEvent; // 通过GUI编程 理解匿名内部类的使用场景 public class Test3 { public static void main(String[] args) { // 创建窗口 JFrame win = new JFrame("登录界面"); JPanel panel = new JPanel(); win.add(panel); // 创建按钮对象 JButton but = new JButton("登录"); // 匿名内部类的使用 // but.addActionListener(new AbstractAction() { // @Override // public void actionPerformed(ActionEvent e) { // JOptionPane.showMessageDialog(win,"点我点我"); // } // }); but.addActionListener(e -> JOptionPane.showMessageDialog(win,"亲亲的")); // 把按钮对象添加到桌布上展示 panel.add(but); // 展示窗口 win.setSize(400,300); win.setLocationRelativeTo(null); win.setVisible(true); } }
常用API
Object类
常用方法:
toString方法” public String toString() 默认是返回当前对象在堆内存中的地址信息
package com.itjiaming.changyongAPI.object_d1; // Object 类中toString方法的使用 public class Test { public static void main(String[] args) { Student s = new Student("郑佳明",'男',88); String rs = s.toString(); System.out.println(rs);//com.itjiaming.changyongAPI.object_d1.Student@1b6d3586 System.out.println(s);//com.itjiaming.changyongAPI.object_d1.Student@1b6d3586 } } class Student{ private String name; private char sex; private int age; public Student() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, char sex, int age) { this.name = name; this.sex = sex; this.age = age; } @Override // toString()方法重写 重写以后返回子类对象的内容 public String toString() { return "Student{" + "name='" + name + '\'' + ", sex=" + sex + ", age=" + age + '}'; } }
equals 方法
package com.itjiaming.changyongAPI.object_d1; public class Test2 { public static void main(String[] args) { Student s = new Student("郑佳明",'男',88); Student s1 = new Student("郑佳明",'男',88); // 比较地址是否相同 System.out.println(s.equals(s1)); } }
package com.itjiaming.changyongAPI.object_d1; import java.util.Objects; public class Test2 { public static void main(String[] args) { Students s = new Students("郑佳明",'男',88); Students s1 = new Students("郑佳明",'男',88); // 比较地址是否相同 System.out.println(s.equals(s1)); } } class Students{ private String name; private char sex; private int age; public Students() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Students(String name, char sex, int age) { this.name = name; this.sex = sex; this.age = age; } // 重写equals方法比较字符串内容 @Override public boolean equals(Object o) { // 判断是否是同一个对象 if (this == o) return true; // this.getClass() if (o == null || getClass() != o.getClass()) return false; // o是学生类型并且o不是null Students students = (Students) o; return sex == students.sex && age == students.age && Objects.equals(name, students.name); } @Override public int hashCode() { return Objects.hash(name, sex, age); } }
Objects类与Object 还是继承关系 官方进行字符串比较时没有对象自己的equals方法而是选择了Objects的equals方法来比较两个对象(Objects的equals方法比较 更安全)
package com.itjiaming.changyongAPI.objects_d2; import java.util.Objects; // Objiects类的常用方法:equals public class Test { public static void main(String[] args) { String s1 = "itjiaming"; String s2 = "itjiaming"; System.out.println(s1.equals(s2));// true // 更安全 更准确 String a = null; String b = new String("dsdsda"); System.out.println(Objects.equals(a,b));// false // 判断是否是null System.out.println(Objects.isNull(a));// true System.out.println(Objects.isNull(b));// fals } }
StringBuilder
StringBuilder是一个可变的字符串类,我们可以把它看成是一个对象容器
作用:提高字符串的操作效率(只创建一个对象),如拼接修改等
package com.itjiaming.changyongAPI.StringBuilder_d1; // 使用StringBulider 操作字符串 public class Test{ public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("a"); sb.append("b"); sb.append("c"); sb.append("d"); sb.append(1); sb.append(4.3); sb.append("sdada"); System.out.println(sb); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("A").append("s").append("中过"); System.out.println(stringBuilder); // As中过 // 反转 stringBuilder.reverse().append("110"); System.out.println(stringBuilder); // 过中sA110 // 取长度 System.out.println(stringBuilder.length()); // 7 // 最终要恢复成String类型 StringBuilder s = new StringBuilder(); s.append("123").append("456"); String ss = s.toString(); check(ss); } public static void check(String data){ System.out.println(data); } }
package com.itjiaming.changyongAPI.StringBuilder_d1; // 打印数组内容 public class Test2 { public static void main(String[] args) { int[] arr1 = null; System.out.println(Test2.toArr(arr1)); int[] arr = {1,2,5,6,2,47,55,555}; System.out.println(toArr(arr)); } // 定义方法接受任意整数数组 返回数组内容格式 public static String toArr(int[] arr){ if (arr != null){ // 开始拼接内容 StringBuilder sb = new StringBuilder("["); for (int i = 0; i < arr.length; i++) { sb.append(arr[i]).append(i == arr.length-1?"":", "); } sb.append("]"); return sb.toString(); }else { return null; } } }
Math类
包含执行基本数字的运算方法,math 类没有提供公开的构造器
都是静态方法不需要创建对象
package com.itjiaming.changyongAPI.Math_d1; import org.omg.CORBA.MARSHAL; public class MathDemo { public static void main(String[] args) { // 取绝对值 System.out.println(Math.abs(-4)); System.out.println(Math.abs(-110.52)); // 返回大于或等于参数的最小(最接近负无穷大) double值,等于一个数学整数。 System.out.println(Math.ceil(5.555555)); System.out.println(Math.ceil(5.0002)); // 返回小于或等于参数的最大(最接近正无穷大) double值,等于一个数学整数。 System.out.println(Math.floor(5.33333)); System.out.println(Math.floor(5.000003)); // 将第一个参数的值返回到第二个参数的幂 System.out.println(Math.pow(2, 3)); // 2^3 // 返回参数中最接近的 long ,其中 long四舍五入为正无穷大。 System.out.println(Math.round(4.55551)); System.out.println(Math.round(4.332)); // 返回值为 double值为正号,大于等于 0.0 ,小于 1.0 。 System.out.println(Math.random()); // 3-9之间的随机数 int a = (int)(Math.random()*7) + 3; System.out.println(a); } }
System类
package com.itjiaming.changyongAPI.System_d1; import java.util.Arrays; public class SystemDemo { public static void main(String[] args) { //终止当前运行的Java虚拟机 // System.exit(0);//JVM正常终止 // 返回当前时间(以毫秒为单位)。 1970-01-01-00.00.00 long time = System.currentTimeMillis(); System.out.println(time); long startTime = System.currentTimeMillis(); // 进行时间计算 性能分析 for (int i = 0; i < 1000000; i++) { System.out.println("输出" + i); } long endTime = System.currentTimeMillis(); System.out.println((endTime - startTime)/1000.0 + "s"); // 将指定源数组中的数组从指定位置复制到目标数组的指定位置 /** * 参数 * src - 源数组。 * srcPos - 源数组中的起始位置。 * dest - 目标数组。 * destPos - 目的地数据中的起始位置。 * length - 要复制的数组元素的数量。 */ int[] arr1 = {10,20,30,40,50,60,70}; int[] arr2 = new int[6]; System.arraycopy(arr1,3,arr2,2,3); System.out.println(Arrays.toString(arr2)); //[0, 0, 40, 50, 60, 0] } }
BigDecimal
用于解决浮点型运算精度失真问题
package com.itjiaming.changyongAPI.bigdecimal_d1; import java.math.BigDecimal; public class Test { public static void main(String[] args) { // 转换一个 double成 BigDecimal ,使用 double通过所提供的规范的字符串表示 Double.toString(double)方法。 double a = 0.1; double b = 0.2; BigDecimal bigDecimal = BigDecimal.valueOf(a); BigDecimal bigDecimal2 = BigDecimal.valueOf(b); BigDecimal c = bigDecimal.add(bigDecimal2); // 加 BigDecimal c2 = bigDecimal.subtract(bigDecimal2); // 减 BigDecimal c3 = bigDecimal.divide(bigDecimal2); // 除 BigDecimal c4 = bigDecimal.multiply(bigDecimal2); // × System.out.println(c); System.out.println(c2); System.out.println(c3); System.out.println(c4); // 转换成double类型 double rs = c.doubleValue(); System.out.println(rs); // 注意BigDecimal 一定要精度运算 BigDecimal aa = BigDecimal.valueOf(10.0); BigDecimal bb = BigDecimal.valueOf(3.0); // BigDecimal cc = aa.divide(bb); // System.out.println(cc);// 报错 /** 参数1 除数 参数2 保留小数 参数3 四舍五入 */ BigDecimal cc = aa.divide(bb,2,BigDecimal.ROUND_HALF_DOWN); System.out.println(cc); // 3.33 } }
日期与时间
Date 类
Date类的对象在java中代表的是当前系统所在的此刻时间日期。
package com.itjiaming.changyongAPI.date_d1; import java.util.Date; // 使用Date类处理时间 获取时间信息 public class DateDemo { public static void main(String[] args) { // 创建 date类对象 代表此刻的时间 Date d = new Date(); System.out.println(d); // 获取时间毫米值 long time = d.getTime(); System.out.println(time); long t = System.currentTimeMillis(); System.out.println(t); // 把时间毫秒值转换成日期对象 long ti = System.currentTimeMillis(); ti += (60 * 60 + 121) * 1000; Date dd = new Date(ti); System.out.println(dd); // 方法二 Date dii = new Date(); dii.setTime(ti); System.out.println(dii); } }
SimpleDateFormat 类
可以对Date对象或时间毫秒值格式化成我们喜欢的时间形式 也可以把字符串的时间形式解析成日期对象
package com.itjiaming.changyongAPI.simpledateformat_d1; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; // 格式化时间 解析时间 public class SimpleDateFormatDemo { public static void main(String[] args) throws ParseException { // 日期对象 获取此刻时间 Date date = new Date(); System.out.println(date); // 格式化日期 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss: EEE a"); // 开始格式化日期对象 String rs = sdf.format(date); System.out.println(rs); // 格式化时间毫秒值 // 获取时间毫秒值 long time = date.getTime(); System.out.println(sdf.format(time)); // 解析时间 成为日期对象 String dateStr = "2021年08月06日 11:11:11"; // 把字符串时间解析成日期对象 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); Date date1 = simpleDateFormat.parse(dateStr); // 往后走2天14小时49分06秒 long time1 = date1.getTime() + (2L*24*60*60 + 14*60*60 + 49*60+6)*1000; // 格式化时间毫秒值 System.out.println(simpleDateFormat.format(time1)); } }
Calendar类
Calendar 代表了系统此刻的日期对应的日历对象 是一个抽象类不能直接创建对象
package com.itjiaming.changyongAPI.calendar_d1; import java.util.Calendar; import java.util.Date; public class CalendarDemo1 { public static void main(String[] args) { // 拿到系统的日历对像 Calendar calendar = Calendar.getInstance(); System.out.println(calendar); // 获取日历信息 int year = calendar.get(Calendar.YEAR); System.out.println(year); int m = calendar.get(Calendar.MONTH) + 1; System.out.println(m); int d = calendar.get(Calendar.DAY_OF_YEAR); System.out.println(d); // add(int field, int amount) //根据日历的规则,将指定的时间量添加或减去给定的日历字段。 // 64天后的时间 calendar.add(calendar.DAY_OF_YEAR, 64); // getTime() //返回一个 Date表示此物体 Calendar的时间值(毫秒从偏移 Epoch “)。 Date date = calendar.getTime(); System.out.println(date); //getTimeInMillis() //以毫秒为单位返回此日历的时间值。 long time = calendar.getTimeInMillis(); System.out.println(time); //set(int field, int value) //将给定的日历字段设置为给定的值。 calendar.set(Calendar.YEAR, 2023); System.out.println(calendar); } }
JDK8开始新增的日期类
package com.itjiaming.changyongAPI.LocalDate_d1; import sun.util.resources.LocaleData; import java.time.LocalDate; public class Test { public static void main(String[] args) { // 获取本地日期对象 LocalDate nowDate = LocalDate.now(); System.out.println("今天的日期" + nowDate); // 年月日 System.out.println(nowDate.getYear()); System.out.println(nowDate.getMonthValue()); System.out.println(nowDate.getDayOfMonth()); // 当年的第几天 几周 月份 System.out.println(nowDate.getDayOfYear()); System.out.println(nowDate.getDayOfWeek()); System.out.println(nowDate.getDayOfWeek().getValue()); System.out.println(nowDate.getMonth()); System.out.println(nowDate.getMonth().getValue()); } }
package com.itjiaming.changyongAPI.localTime_d1; import java.time.LocalTime; public class Test { public static void main(String[] args) { LocalTime nowTime = LocalTime.now(); System.out.println("现在的时间" + nowTime); // 时分秒纳秒 System.out.println(nowTime.getHour()); System.out.println(nowTime.getMinute()); System.out.println(nowTime.getSecond()); System.out.println(nowTime.getNano()); } }
时间戳 Instant
package com.itjiaming.changyongAPI.instant_d1; import java.time.Instant; import java.time.ZoneId; import java.util.Date; public class Test { public static void main(String[] args) { // 得到时间戳对象 Instant instant = Instant.now(); System.out.println(instant); // 系统此刻的时间按戳 Instant instant1 = Instant.now(); System.out.println(instant1.atZone(ZoneId.systemDefault())); //如何返回DATE对象 Date date = Date.from(instant); System.out.println(date); Instant instant2 = date.toInstant(); System.out.println(instant2); } }
DateTimeFormatter
日期与时间格式器 调用format方法
package com.itjiaming.changyongAPI.dateTimeFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Test { public static void main(String[] args) { // 此刻日期对象 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime); // 解析格式化 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss EEE a"); // 正向格式化 String s = dateTimeFormatter.format(localDateTime); System.out.println(s); } }
包装类
其实就是八种基本数据类型的引用类型
基本数据类型 | 引用数据类型 |
---|---|
byte 1 | Byte |
short 2 | Short |
int 4 | Interger |
long 8 | Long |
char 2 | Character |
float 4 | Float |
double 8 | Double |
boolean 1位 | Boolean |
自动装箱 基本数据类型可以直接赋值给引用类型
自动拆箱
public class Test { public static void main(String[] args) { String number = "23"; // 转换成整数 int s = Integer.parseInt(number); System.out.println(s); int a = Integer.valueOf(number); System.out.println(a); } }
正则表达式
正则表达式可以用一些规定的字符来制定规则 并用来校验数据格式的合法性
public class RegexDemo1 { public static void main(String[] args) { // 校验 QQ 号 必须是6-20位数字 // 正则表达式 System.out.println(checkQQ("444554")); System.out.println(checkQQ("444554p")); System.out.println(checkQQ("44")); System.out.println(checkQQ(null)); } public static boolean checkQQ(String qq){ return qq != null && qq.matches("\\d{6,20}"); } }
匹配规则
Arrays类
数组操作工具类 操作数组元素
package com.itjiaming.arrays_d1; import java.util.Arrays; public class ArraysDemo { public static void main(String[] args) { // 学会arrays类常用API int[] arr = {5,4,8,5,1,45,51,21,0,254,551,2,545,88}; // 打印数组内容 String rs = Arrays.toString(arr); System.out.println(rs); // 排序 默认升序 Arrays.sort(arr); System.out.println(Arrays.toString(arr)); // 二分搜索技术(前提数组必须排好序才可以) int index = Arrays.binarySearch(arr,88); System.out.println(index); } }
package com.itjiaming.arrays_d1; import java.util.Arrays; import java.util.Comparator; // 自定义数组的排序规则 public class ArraysDemo2 { public static void main(String[] args) { // Comparator比较器对象 int[] ages = {12,5,85,8,55,84,36,23}; // 升序排序 Arrays.sort(ages); System.out.println(Arrays.toString(ages)); // 降序排序 (自定义比较器只能支持引用类型的排序) Integer[] ages1 = {12,5,85,8,55,84,36,23}; /** * 参数一 被排序的数组 必须是引用类型 * 参数二 匿名内部类对象 代表一个比较器对象 * */ Arrays.sort(ages1, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 指定比较规则 // if (o1 < o2){ return 1; }else if (o1 > o2){ return -1; } return 0; //return o1 - o2; // 升序 return o2 - o1; // 降序 } }); System.out.println(Arrays.toString(ages1)); System.out.println("+++++++++++++++++++++++"); Student[] students = new Student[3]; students[0] = new Student("张三1",12,175.2); students[1] = new Student("张三2",2,178.5); students[2] = new Student("张三3",22,179.7); System.out.println(Arrays.toString(students)); // Arrays.sort(students); 直接排会崩溃 // 自定义比较器 Arrays.sort(students, new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 自定义比较规则 // return o1.getAge() - o2.getAge(); // 小数 比较方法 // return Double.compare(o1.getHeight(),o2.getHeight()); 升序 return Double.compare(o2.getHeight(),o1.getHeight()); // 降序 } }); System.out.println(Arrays.toString(students)); } } class Student{ private String name; private int age; private double height; 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 getHeight() { return height; } public void setHeight(double height) { this.height = height; } public Student() { } public Student(String name, int age, double height) { this.name = name; this.age = age; this.height = height; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}'; } }
常见算法
选择排序
第一个值开始 如果比他小就交换位置 选择数组长度-1轮
package com.itjiaming.changjiansuanfa_d1; import java.util.Arrays; public class Test { public static void main(String[] args) { // 定义数组 int[] arr = {5,1,3,2}; // 0 1 2 3 // 定义循环选择几轮 for (int i = 0; i < arr.length-1; i++) { // 定义内部循环选择几次 // i= 0 j = 1 2 3 // i = 1 j= 2 3 // i = 2 j = 3 for (int j = i+1; j < arr.length; j++) { // 当前位 arr[i] // 如果有比当前位小的 则交换 if (arr[i] > arr[j]){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } System.out.println(Arrays.toString(arr)); } }
二分查找
在数据排好序以后才能使用二分查找
package com.itjiaming.changjiansuanfa_d1; public class Test2 { public static void main(String[] args) { int[] arr = {12,14,16,25,28,30,35,88,100}; System.out.println(binarySearch(arr,25)); System.out.println(binarySearch(arr,245)); } /** * 二分查找的算法 * @param arr * @param data * @return 元素不存在返回-1 */ public static int binarySearch(int[] arr, int data){ // 定义 左边 位置 和 右边位置 int left = 0; int right = arr.length - 1; // 开始循环折半查询 while (left <= right){ // 取中间索引 int middleIndex = (left + right)/2; //判断中间位置的元素 和要找的元素的大小情况 if (data > arr[middleIndex]){ // 往右边找 左位置更新为中间位置+1 left = middleIndex + 1; }else if (data < arr[middleIndex]){ // 往左找 右边位置 = 中间位置 - 1 right = middleIndex - 1; }else { return middleIndex; } } return -1; // 查无此元素 } }
Lambda表达式
lambda表达式是JDK8以后开始的一种新语法形式
简化匿名内部类的代码写法
格式:
(匿名内部类被重写的形参列表) -> { 被重写的方法体 } 注:->是语法形式
注意:lambda只能简化函数式接口(只有一个抽象方法)的匿名内部类
package com.itjiaming.lambda_d1; public class LambdaDemo2 { public static void main(String[] args) { // lambda只能简化函数式接口内只有一个抽象方法的匿名内部类 // Swimming s1 = new Swimming() { // @Override // //匿名内部类 // public void swin() { // System.out.println("老师会游泳"); // } // }; // go(s1); // lambda表达式简化匿名内部类 Swimming s2 = () ->{ System.out.println("老师会游泳"); }; go(s2); System.out.println("==================="); go(new Swimming() { @Override public void swin() { System.out.println("学生现在也会游泳"); } }); System.out.println("================"); go(() ->{ System.out.println("学生现在也会游泳"); }); } public static void go(Swimming s){ System.out.println("开始"); s.swin(); System.out.println("结束"); } } @FunctionalInterface // 函数式接口里面只能有一个抽象方法 interface Swimming{ void swin(); }
package com.itjiaming.lambda_d1; import javax.swing.*; import java.awt.event.ActionEvent; import java.util.Arrays; import java.util.Comparator; public class LambdaDemo3 { public static void main(String[] args) { Integer[] ages = {12,8,88,61,55}; Arrays.sort(ages, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); System.out.println(Arrays.toString(ages)); System.out.println("=================+++++++=========="); // 简化 Arrays.sort(ages, (Integer o1, Integer o2) ->{ return o2 - o1; }); System.out.println(Arrays.toString(ages)); JButton btn = new JButton("大按钮"); JFrame win = new JFrame("登录页面"); // btn.addActionListener(new AbstractAction() { // @Override // public void actionPerformed(ActionEvent e) { // System.out.println("有人点我!!!!"); // } // }); btn.addActionListener((ActionEvent e) -> { System.out.println("有人点我!!!!"); }); win.add(btn); win.setSize(400,300); win.setVisible(true); } }
lambda的省略规则:
// 简化 Arrays.sort(ages, (o1,o2) ->{ return o2 - o1; }); Arrays.sort(ages, (o1,o2) -> o2 - o1); btn.addActionListener(e -> { System.out.println("有人点我!!!!"); }); btn.addActionListener(e -> System.out.println("有人点我!!!!"));
常见的数据结构
栈
先进后出 后进先出 压栈或进栈 弹栈或出栈
实际应用:压子弹
队列
先进先出 后进后出 入队 出队 从后端用前端出
应用:银行叫号系统
数组
数组根据索引查询速度快 删除效率低 添加效率低 删除添加会用移动算法
链表
链表中的元素在内存中不连续存储 每个元素节点包含数据值和下一个元素的地址
查询慢 索引慢 增删相对数组比较快
双链表
二叉树
一个节点最多有两个分支
二叉树特点:
二叉查找树(二叉排序树):左子树上的所有节点都小于根节点的值 小的放左边大的放右边 提高增删改查
二叉平衡树:满足二叉查找树的条件下 使二叉树变矮
要求:任意节点左右子树高度不超过一
红黑树:提高数据的增删改查效率 通过红黑规则平衡
红黑规则:根节点必须是黑色 叶子节点是黑色的 黑节点下必须是红色 左子树与右子树的黑色节点必须相同
默认添加红色节点效率高
集合的概述
集合与数组一样都是容器
数组定义后类型长度固定 在增删数据时都需要放弃原数组或者移位
数组使用场景:数据元素类型个数确定
集合是JAVA中存储对象数据的一种容器
集合大小不固定类型不固定
集合适合元素的增删操作
注意:集合只能存储引用类型数据 如果存储基本类型可以用包装类
集合对泛型的支持 (泛型<E>) 约束集合只能操作某种数据类型 只支持引用数据类型
// 泛型 约束集合的数据类型 Collection<String> list3 = new ArrayList(); list3.add("张三"); //list3.add(44); // 报错 System.out.println(list3); // 集合和泛型不支持进本数据类型 Collection<Integer> list4 = new ArrayList(); list4.add(55); list4.add(555); list4.add(5554); list4.add(55545); System.out.println(list4);
Collection
单列集合 每个元素只有一个值
collection 是一个接口
特点:List集合是子接口继承Collection 添加元素有序 可重复 有索引
ArrayList,LinekList是List的实现方法
package com.itjiaming.collection_d1; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; // 明确collection集合体系的特点 public class CollectionDemo1 { public static void main(String[] args) { // List 有序 可重复 有索引 Collection list = new ArrayList(); list.add("java"); list.add("java"); list.add(44); list.add(44); list.add(44); System.out.println(list); // Set 无序 不重复 无索引 Collection list1 = new HashSet(); list1.add("java"); list1.add("java"); list1.add(44); list1.add(44); list1.add(44); list1.add(78); list1.add("dsa"); list1.add("dwdw"); System.out.println(list1); // [java, dsa, dwdw, 44, 78] } }
collection常用的API
package com.itjiaming.collection_api; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; public class Test { public static void main(String[] args) { Collection<String> c = new ArrayList<>(); // 添加元素 返回值是bollen类型 c.add("java"); c.add("张三"); c.add("java"); c.add("python"); System.out.println(c); // 清空集合元素 //c.clear(); // System.out.println(c); //判断集合是否为空 System.out.println(c.isEmpty()); // 获取集合的大小 返回值int System.out.println(c.size()); // 集合中是否包含某一元素 返回值bollen 区分大小写 System.out.println(c.contains("张三")); // 删除元素 返回值类型 bollens 重复的默认删除第一个 System.out.println(c.remove("java")); System.out.println(c); // 把集合准换成数组 Object[] arrs = c.toArray(); System.out.println(Arrays.toString(arrs)); System.out.println("=================="); Collection<String> c1 = new ArrayList<>(); c1.add("mysql"); c1.add("php"); Collection<String> c2 = new ArrayList<>(); c2.add("张三"); c2.add("李四"); c1.addAll(c2); // 把c2的元素拷贝到c1中 System.out.println(c1); //[mysql, php, 张三, 李四] } }
collection的遍历
迭代器遍历(集合专用的) Iterator
package com.itjiaming.collection_bianli; import java.security.spec.RSAOtherPrimeInfo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Test { public static void main(String[] args) { Collection<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); System.out.println(list); // 得到当前迭代器对象 Iterator<String> it = list.iterator(); // System.out.println(it.next()); //张三 // System.out.println(it.next()); //李四 // System.out.println(it.next()); //王五 // System.out.println(it.next()); //赵六 // 定义循环遍历 hasNext询问是否有元素 while (it.hasNext()){ String s = it.next(); System.out.print(s + " "); } System.out.println("===================="); } }
foreach/增强for遍历 可以遍历数组和集合 实现Iterable接口的类才可以使用Collection接口已经实现了Iterable
格式:for(元素类型 变量名:数组或者Collection集合) { 在此处使用变量即可,该变量就是元素 }
public static void main(String[] args) { Collection<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); for (String ele:list){ System.out.println(ele); }
lambda表达式遍历集合 Collection结合lambda遍历API
使用 集合.foreach方法
// lambda表达式 list.forEach(s -> System.out.println(s));
List集合
有序 可重复 有索引
package com.itjiaming.collection_d1.list_d1; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { // 创建ArrayList 对象 List<String> list = new ArrayList<>(); // 经典代码 list.add("张三"); list.add("lisi"); list.add("wam"); // 在某个索引位置加入数据 list.add(2,"dsd"); System.out.println(list); // 根据索引删除数据 返回值为被删除的元素 System.out.println(list.remove(2)); // 根据索引返回具体位置的元素 返回值为索引的元素 System.out.println(list.get(2)); // 修改索引位置的元素值 返回要被修改的值 System.out.println(list.set(1, "ooo")); System.out.println(list); } }
遍历方式
ArrayList 集合底层原理
LinkedList集合底层原理
LinkedList集合的功能 (双链表)
package com.itjiaming.collection_d1.linkedlist; import java.util.LinkedList; // linkedlist独有的功能 public class Test { public static void main(String[] args) { // LinkedList可以完成队列和栈结构(双链表) // 栈 LinkedList<String> stack = new LinkedList<>(); // 入栈 stack.push("第一颗子弹"); stack.addFirst("第二颗子弹"); stack.addFirst("第三颗子弹"); stack.addFirst("第四颗子弹"); System.out.println(stack); // 出栈 System.out.println(stack.pop()); System.out.println(stack.removeFirst()); System.out.println(stack.removeFirst()); System.out.println(stack.removeFirst()); System.out.println(stack); // 队列 LinkedList<String> queue = new LinkedList<>(); // 入队 queue.addLast("1号"); queue.addLast("2号"); queue.addLast("3号"); queue.addLast("4号"); queue.addLast("5号"); System.out.println(queue); // 出队 System.out.println(queue.removeFirst()); System.out.println(queue.removeFirst()); System.out.println(queue.removeFirst()); System.out.println(queue.removeFirst()); System.out.println(queue); } }
// 遍历删除元素 package com.itjiaming.collection_d1.linkedlist; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Tets2 { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("php"); list.add("java"); list.add("java"); list.add("python"); list.add("python"); list.add("c++"); System.out.println(list); // // 迭代器遍历 删除所有java // Iterator<String> it = list.iterator(); // while (it.hasNext()){ // if (it.next().equals("c++"));{ // //list.remove("java"); 会报错 // it.remove(); // 删除当前所在元素 并且不会后移 // } // } // System.out.println(list); // foreach遍历删除 存在BUG // lambda表达式 也存在BUGl // for 循环 for (int i = 0; i < list.size(); i++) { String ele = list.get(i); if ("java".equals(ele)){ list.remove("java");// 删除不干净 i--; // 可以删干净 } } // for (int i = list.size()-1; i >= 0 ; i--) { // String ele = list.get(i); // if ("java".equals(ele)){ // list.remove("java"); // } // } System.out.println(list); } }
泛型
可以在编译阶段约束操作的数据类型 并进行检查
格式:<数据类型> 只支持引用数据类型
集合体系的全部接口和实现类都是支持泛型的使用
泛型的好处: 统一类型
泛型使用场景: 类后面-->泛型类 方法申明上-->泛型方法 接口后面-->泛型接口
泛型类
格式:修饰符class类名<泛型变量>{}
public class MyArrayList<T>{}
T 为任意标识 常见的如E,T, K,V等
作用:编译阶段可以指定数据类型
package com.itjiaming.collection_d1.linkedlist; import com.sun.xml.internal.ws.api.model.wsdl.WSDLPortType; import java.util.ArrayList; public class Test3 { public static void main(String[] args) { // 泛型设计 MyArrayList<String> list = new MyArrayList<>(); list.add("张三"); list.add("张三"); // list.remode("张三"); System.out.println(list); } } class MyArrayList<E>{ private ArrayList list = new ArrayList(); public void add(E e){ list.add(e); } public void remode(E e){ list.remove(e); } @Override public String toString() { return list.toString(); } }
泛型方法:
格式:修饰符<泛型变量>方法返回子 方法名称(形参列表){}
作用:方法中可以使用泛型接收一切实际类型的参数,方法具备通用性。
package com.itjiaming.collection_d1.linkedlist; import java.util.ArrayList; public class Test3 { public static void main(String[] args) { String[] names = {"张三","李四","王五"}; printArray(names); Integer[] ages = {10,20,30}; printArray(ages); } // 接受一切类型的数组 public static <T> void printArray(T[] arr){ if (arr!=null){ StringBuilder sb = new StringBuilder("["); for (int i = 0; i < arr.length; i++) { sb.append(arr[i]).append(i==arr.length-1?"":", "); } sb.append("]"); System.out.println(sb); }else { System.out.println(arr); } } }
自定义泛型接口
格式:修饰符 interface 接口名称<泛型变量>{}
package com.itjiaming.collection_d1.linkedlist; // 定义接口操作学生数据和老师数据的增删改查 public interface Test3<E> { void add(E e); void delete(int id); void update(E e); E queryById(int id); } class Teacher{ } class TeacherData implements Test3<Teacher>{ @Override public void add(Teacher teacher) { } @Override public void delete(int id) { } @Override public void update(Teacher teacher) { } @Override public Teacher queryById(int id) { return null; } } class Studernt{ } class StudentData implements Test3<Studernt>{ @Override public void add(Studernt studernt) { } @Override public void delete(int id) { } @Override public void update(Studernt studernt) { } @Override public Studernt queryById(int id) { return null; } }
泛型的通配符:?可以在使用泛型时代表一切类型
泛型额上下限:?extend 父类:?必须是父类或者其子类 泛型上限
?super 父类:?必须是父类或者其父类 泛型下限
package com.itjiaming.collection_d1.linkedlist; import java.util.ArrayList; // 定义接口操作学生数据和老师数据的增删改查 public interface Test3<E> { public static void main(String[] args) { ArrayList<BYD> byds = new ArrayList<>(); byds.add(new BYD()); go(byds); ArrayList<BMW> bmws = new ArrayList<>(); bmws.add(new BMW()); go(bmws); } // <?> 通配符 // <? extends Car> 泛型上限 public static void go(ArrayList<? extends Car> cars){ } } class Car{ } class BYD extends Car{ } class BMW extends Car{ }
Set系列集合
无序 不重复 无索引
Set集合实现特点:HashSet LinkedHashSet(有序) TreeSet
package com.itjiaming.set_d1.setjihe; import java.util.HashSet; import java.util.Set; public class SetDemo { public static void main(String[] args) { // 实现类 HashSet LinkedHashSet(有序) TreeSet Set<String> sets = new HashSet<>(); sets.add("dsd"); sets.add("dsd"); sets.add("dsdgg"); sets.add("dsdewq"); sets.add("dseqed"); sets.add("ee"); System.out.println(sets); //无序 不重复 无索引 } }
set集合的功能与collection基本一致
HashSet集合底层采取哈希表存取数据的
package com.itjiaming.set_d1.setjihe; public class Test { public static void main(String[] args) { // 获取哈希值 String name = "sdsad"; String name1 = "sdsdwad"; System.out.println(name.hashCode()); System.out.println(name1.hashCode()); } }
collections
Map集合
双列集合 每个元素包含两个值 键值对集合
格式:key = value(键值对元素)
map集合格式 {key1 = value1, ......}
使用场景:购物系统
map集合是 无序 不重复 无索引
实现类:HashMap
package com.itjiaming.d1_map; import java.util.HashMap; import java.util.Map; // map集合体系 键 无序 不重复 无索引 public class MapDemo { public static void main(String[] args) { // 创建Map集合对象 Map<String ,Integer> maps = new HashMap<>(); maps.put("袜子",45); maps.put("帽子",5); maps.put("帽子",55); //覆盖5 maps.put("鞋子",4); maps.put("枸杞",4); maps.put(null, null); System.out.println(maps); } }
实现类:LinkedHashMap: 元素是按照键有序 不重复 无索引
实现类:TreeMap 元素按照键排序 不重复 无索引
Map集合常用的API
package com.itjiaming.d2.mapapi; import java.util.Collection; import java.util.HashMap; import java.util.Map; public class MapTest { public static void main(String[] args) { Map<String, Integer> maps = new HashMap<>(); maps.put("手机", 10); maps.put("娃娃", 11); maps.put("电脑", 12); maps.put("手机", 15); maps.put("平板", 10); maps.put("耳机", 10); System.out.println(maps); System.out.println("=================="); // 清空集合 // maps.clear(); // System.out.println(maps); // 判断集合是否为空 System.out.println(maps.isEmpty()); // 根据键获取对应的值 System.out.println(maps.get("手机")); // 根据键删除整个元素 返回被删除键对应的值 maps.remove("电脑"); System.out.println(maps); // 判断是否包含某个键 返回值boolean System.out.println(maps.containsKey("电脑")); System.out.println(maps.containsKey("平板")); // 是否包含值 System.out.println(maps.containsValue(11)); System.out.println(maps.containsValue(155)); // 获取全部键的集合 System.out.println(maps.keySet()); System.out.println("==============="); // 所有的值的集合 Collection<Integer> a = maps.values(); System.out.println(a); System.out.println(maps.values()); // 集合的大小 System.out.println(maps.size()); // 合并集合 Map<String, Integer> mapss = new HashMap<>(); mapss.put("手ds机", 10); mapss.put("娃dd娃", 11); mapss.put("电sa脑", 12); mapss.put("手机d", 175); maps.putAll(mapss); // 把mapss中的元素拷贝到maps中 System.out.println(maps); System.out.println(mapss); } }
创建不可变集合
Stream流
简化数组和集合操作的API
package com.itjiaming.stream_d1; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; public class Test { public static void main(String[] args) { List<String> names = new ArrayList<>(); Collections.addAll(names,"张无忌","张三丰","周芷若","赵敏","张强"); // 把姓张的放在新集合中 List<String> zhangList = new ArrayList<>(); for (String name : names) { if (name.startsWith("张")){ zhangList.add(name); } } System.out.println(zhangList); // 使用stream实现 names.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s)); } }