15.日期与时间

1)Date

package com.itheima.d1_date;import java.time.Instant;
import java.time.ZoneId;
import java.util.Date;/**目标:学会使用Date类处理时间,获取时间的信息*/
public class DateDemo1 {public static void main(String[] args) {// 1、创建一个Date类的对象:代表系统此刻日期时间对象Date d = new Date();System.out.println(d);// 2、获取时间毫秒值long time = d.getTime();System.out.println(time);
//        long time1 = System.currentTimeMillis();
//        System.out.println(time1);System.out.println("----------------------------");// 1、得到当前时间Date d1 = new Date();System.out.println(d1);// 2、当前时间往后走 1小时  121slong time2 = System.currentTimeMillis();time2 += (60 * 60 + 121) * 1000;// 3、把时间毫秒值转换成对应的日期对象。// Date d2 = new Date(time2);// System.out.println(d2);Date d3 = new Date();d3.setTime(time2);System.out.println(d3);}
}

2)SimpleDateFormat

package com.itheima.d2_simpledateformat;import javax.xml.crypto.Data;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class SimpleDateFormatDemo2 {public static void main(String[] args) throws ParseException {// 目标: 学会使用SimpleDateFormat解析字符串时间成为日期对象。// 有一个时间 2021年08月06日 11:11:11 往后 2天 14小时 49分 06秒后的时间是多少。// 1、把字符串时间拿到程序中来String dateStr = "2021年08月06日 11:11:11";// 2、把字符串时间解析成日期对象(本节的重点):形式必须与被解析时间的形式完全一样,否则运行时解析报错!SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");Date d = sdf.parse(dateStr);// 3、往后走2天 14小时 49分 06秒,值可能会很大,超出范围会失真,所以在“2”的后面加了Llong time = d.getTime() + (2L*24*60*60 + 14*60*60 + 49*60 + 6) * 1000;// 4、格式化这个时间毫秒值就是结果System.out.println(sdf.format(time));}
}

3)Calendar

16.JDK8新增日期类

1)概述、LocalTime /LocalDate / LocalDateTime

2)Instant

//2、系统此刻的时间戳怎么办?
Instant instant1 = Instant.now();
System.out.println(instant1.atZone(ZoneId.systemDefault()));

3)DateTimeFormatter

1] 在JDK8中,引入了一个全新的日期与时间格式器DateTimeFormatter。

2] 正反都能调用format方法

package com.itheima.d4_jdk8_time;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Demo06DateTimeFormat {public static void main(String[] args) {// 本地此刻  日期时间 对象LocalDateTime ldt = LocalDateTime.now();System.out.println(ldt);// 解析/格式化器        (EEE代表星期几,a代表上午或下午)DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");// 正向格式化System.out.println(dtf.format(ldt));// 逆向格式化System.out.println(ldt.format(dtf));// 解析字符串时间(这里是格式化器进行解析)DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 解析当前字符串时间成为本地日期时间对象LocalDateTime ldt1 = LocalDateTime.parse("2019-11-11 11:11:11" ,  dtf1);System.out.println(ldt1);System.out.println(ldt1.getDayOfYear());}
}

4)Duration/Period

5)ChronoUnit

 17.包装类

package com.itheima.d5_integer;//目标:明白包装类的概念,并使用。
public class Test {public static void main(String[] args) {int a = 10;Integer a1 = 11;Integer a2 = a; // 自动装箱System.out.println(a);System.out.println(a1);Integer it = 100;int it1 = it; // 自动拆箱System.out.println(it1);double db = 99.5;Double db2 = db; // 自动装箱了double db3 = db2; // 自动拆箱System.out.println(db3);// int age = null; // 报错了!Integer age1 = null;Integer age2 = 0;System.out.println("-----------------");// 1、包装类可以把基本类型的数据转换成字符串形式。(没啥用)Integer i3 = 23;String rs = i3.toString();System.out.println(rs + 1);String rs1 = Integer.toString(i3);System.out.println(rs1 + 1);// 可以直接+字符串得到字符串类型String rs2 = i3 + "";System.out.println(rs2 + 1);System.out.println("-----------------");String number = "23";//转换成整数// int age = Integer.parseInt(number);int age = Integer.valueOf(number);//使用这种方法更好记一点System.out.println(age + 1);String number1 = "99.9";//转换成小数
//        double score = Double.parseDouble(number1);double score = Double.valueOf(number1);System.out.println(score + 0.1);}
}

18.正则表达式

1)概述

正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性。

2)匹配规则

3)常见案例

package com.itheima.d6_regex;import java.util.Arrays;
import java.util.Scanner;public class RegexTest3 {public static void main(String[] args) {// 目标:校验 手机号码 邮箱  电话号码// checkPhone();// checkEmail();// checkTel();}public static void checkTel(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的电话号码:");String tel = sc.next();// 判断邮箱格式是否正确   027-3572457  0273572457if(tel.matches("0\\d{2,6}-?\\d{5,20}")){System.out.println("格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}public static void checkEmail(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的注册邮箱:");String email = sc.next();// 判断邮箱格式是否正确   3268847878@qq.com// 判断邮箱格式是否正确   3268847dsda878@163.com// 判断邮箱格式是否正确   3268847dsda878@pci.com.cnif(email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){System.out.println("邮箱格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}public static void checkPhone(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的注册手机号码:");String phone = sc.next();// 判断手机号码的格式是否正确if(phone.matches("1[3-9]\\d{9}")){System.out.println("手机号码格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}
}

4)在方法中的应用

package com.itheima.d6_regex;
/**目标:正则表达式在方法中的应用。public String[] split(String regex):-- 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。public String replaceAll(String regex,String newStr)-- 按照正则表达式匹配的内容进行替换*/
public class RegexDemo04 {public static void main(String[] args) {String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";String[] arrs = names.split("\\w+");for (int i = 0; i < arrs.length; i++) {System.out.println(arrs[i]);}String names2 = names.replaceAll("\\w+", "  ");System.out.println(names2);}
}

5)正则表达式爬取信息

package com.itheima.d6_regex;import java.util.regex.Matcher;
import java.util.regex.Pattern;//拓展:正则表达式爬取信息中的内容。(了解)
public class RegexDemo05 {public static void main(String[] args) {String rs = "来黑马程序学习Java,电话020-43422424,或者联系邮箱" +"itcast@itcast.cn,电话18762832633,0203232323" +"邮箱bozai@itcast.cn,400-100-3233 ,4001003232";// 需求:从上面的内容中爬取出 电话号码和邮箱。// 1、定义爬取规则,字符串形式           | 代表分组的意思String regex = "(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})" +"|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})";// 2、把这个爬取规则编译成匹配对象。Pattern pattern = Pattern.compile(regex);// 3、得到一个内容匹配器对象Matcher matcher = pattern.matcher(rs);// 4、开始找了while (matcher.find()) {String rs1 = matcher.group();System.out.println(rs1);}}
}

19.Arrays类

1)概述

2)Arrays类对于Comparator比较器的支持

package com.itheima.d7_arrays;import java.util.Arrays;
import java.util.Comparator;public class ArraysDemo2 {public static void main(String[] args) {// 目标:自定义数组的排序规则:Comparator比较器对象。// 1、Arrays的sort方法对于有值特性的数组是默认升序排序int[] ages = {34, 12, 42, 23};Arrays.sort(ages);System.out.println(Arrays.toString(ages));// 2、需求:降序排序!(自定义比较器对象,只能支持引用类型的排序!!)Integer[] ages1 = {34, 12, 42, 23};/**参数一:被排序的数组 必须是引用类型的元素参数二:匿名内部类对象,代表了一个比较器对象。*/Arrays.sort(ages1, new Comparator<Integer>() {@Overridepublic 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("吴磊",23 , 175.5);students[1] = new Student("谢鑫",18 , 185.5);students[2] = new Student("王亮",20 , 195.5);System.out.println(Arrays.toString(students));// Arrays.sort(students);  // 直接运行奔溃,不知道按什么排Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 自己指定比较规则// return o1.getAge() - o2.getAge(); // 按照年龄升序排序!// return o2.getAge() - o1.getAge(); // 按照年龄降序排序!!//按照身高降序排序!! 如果是170.3 , 170.0 这两个相减 = 0.3 int之后就会变成 0 这样就可能不会调换顺序,就会有问题所以不能用这样的写法//return (int) (o1.getHeight(), o2.getHeight());// return Double.compare(o1.getHeight(), o2.getHeight()); // 比较浮点型可以这样写 升序return Double.compare(o2.getHeight(), o1.getHeight()); // 比较浮点型可以这样写  降序}});System.out.println(Arrays.toString(students));}
}//————————————————————————————————————————————————————————————————————————————————————————————
package com.itheima.d7_arrays;public class Student {private String name;private int age;private double height;public Student() {}public Student(String name, int age, double height) {this.name = name;this.age = age;this.height = 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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", height=" + height +'}';}
}

20.常见算法

1)冒泡排序

2)选择排序

package com.itheima.d8_sort_binarysearch;import java.util.Arrays;//目标:学会使用选择排序的方法对数组进行排序。
public class Test1 {public static void main(String[] args) {// 1、定义数组int[] arr = {5, 1, 3, 2};//           0  1  2  3// 2、定义一个循环控制选择几轮: arr.length - 1for (int i = 0; i < arr.length - 1; i++) {// i = 0   j =  1  2  3// i = 1   j =  2  3// i = 2   j =  3// 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));}
}

3)二分查找

package com.itheima.d8_sort_binarysearch;//目标:理解二分搜索的原理并实现。
public class Test2 {public static void main(String[] args) {// 1、定义数组int[] arr = {10, 14, 16, 25, 28, 30, 35, 88, 100};//System.out.println(binarySearch(arr , 35));System.out.println(binarySearch(arr , 350));}/*** 二分查找算法的实现* @param arr  排序的数组* @param data 要找的数据* @return  索引,如果元素不存在,直接返回-1*/public static int binarySearch(int[] arr, int data){// 1、定义左边位置  和 右边位置int left = 0;int right = arr.length - 1;// 2、开始循环,折半查询。while (left <= right){// 取中间索引int middleIndex = (left + right) / 2;// 3、判断当前中间位置的元素和要找的元素的大小情况if(data > arr[middleIndex]) {// 往右边找,左位置更新为 = 中间索引+1left = middleIndex + 1;}else if(data < arr[middleIndex]) {// 往左边找,右边位置 = 中间索引 - 1right = middleIndex - 1;}else {return middleIndex;}}return -1; // 查无此元素}
}

实现步骤是什么样的? 

1]定义变量记录左边和右边位置。

2]使用while循环控制查询(条件是左边位置<=右边位置)

3]循环内部获取中间元素索引

4]判断当前要找的元素如果大于中间元素,左边位置=中间索引+1

5]判断当前要找的元素如果小于中间元素,右边位置=中间索引-1

6]判断当前要找的元素如果等于中间元素,返回当前中间元素索引。

结论:二分查找正常的检索条件应该是开始位置min <= 结束位置max

21.Lambda表达式

1)Lambda概述

package com.itheima.d9_lambda;public class LambdaDemo1 {public static void main(String[] args) {// 目标:学会使用Lambda的标准格式简化匿名内部类的代码形式Animal a = new Animal() {@Overridepublic void run() {System.out.println("乌龟跑的很慢~~~~~");}};a.run();// 注意:lambda并不是可以简化所有匿名匿名内部类形式!!,这样的写法是不可行的,具体的写法要看LambdaDemo2/*Animal a1 = () -> {System.out.println("乌龟跑的很慢~~~~~");};a1.run();*/}
}abstract class Animal{public abstract void run();
}//————————————————————————————————————————————————————————————————————————
package com.itheima.d9_lambda;public class LambdaDemo2 {public static void main(String[] args) {// 目标:学会使用Lambda的标准格式简化匿名内部类的代码形式// 注意:Lambda只能简化接口中只有一个抽象方法的匿名内部类形式(函数式接口)/*Swimming s1 = new Swimming() {@Overridepublic void swim() {System.out.println("老师游泳贼溜~~~~~");}};Swimming s1 = () -> {System.out.println("老师游泳贼溜~~~~~");};*///代码简化Swimming s1 = () -> System.out.println("老师游泳贼溜~~~~~");go(s1);System.out.println("-----------简化----------");/*go(new Swimming() {@Overridepublic void swim() {System.out.println("学生游泳很开心~~~");}});go(() ->{System.out.println("学生游泳很开心~~~");});*///代码简化go(() -> System.out.println("学生游泳很开心~~~"));}public static void go(Swimming s){System.out.println("开始。。。");s.swim();System.out.println("结束。。。");}
}@FunctionalInterface // 一旦加上这个注解必须是函数式接口,里面只能有一个抽象方法
interface Swimming{void swim();
}

2)Lambda实战-简化常见函数式接口

3)Lambda表达式的省略规则

21.集合

1)概述

集合和数组都是容器。

数组的特点

1]数组定义完成并启动后,类型确定、长度固定。

2]适合元素的个数和类型确定的业务场景,不适合做需要增删数据操作。

数组适合的场景:当业务数据的个数是固定的,且都是同一批数据类型的时候,可以采取定义数组存储

集合的特点

(java中存储对象数据的一种容器)

1]集合的大小不固定,启动后可以动态变化,类型也可以选择不固定。集合更像气球。

2]集合非常适合做元素的增删操作。

注意:集合中只能存储引用类型的数据,如果要存储基本类型的数据可以选用包装类

集合适用的场景:数据的个数不确定,需要进行增删元素的时候

总结

①数组和集合的元素存储的个数问题。

1]数组定义后类型确定,长度固定

2]集合类型可以不固定,大小是可变的。

②数组和集合存储元素的类型问题。

1]数组可以存储基本类型和引用类型的数据。

2]集合只能存储引用数据类型的数据。

2)体系特点

 

3)Collection的常用API

4)集合的遍历方式

1]方式一:迭代器

package com.itheima.d3_collection_traversal;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/**目标:Collection集合的遍历方式。什么是遍历? 为什么开发中要遍历?遍历就是一个一个的把容器中的元素访问一遍。开发中经常要统计元素的总和,找最值,找出某个数据然后干掉等等业务都需要遍历。Collection集合的遍历方式是全部集合都可以直接使用的,所以我们学习它。Collection集合的遍历方式有三种:(1)迭代器。(2)foreach(增强for循环)。(3)JDK 1.8开始之后的新技术Lambda表达式(了解)a.迭代器遍历集合。-- 方法:public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的boolean hasNext():判断是否有下一个元素,有返回true ,反之。E next():获取下一个元素值!--流程:1.先获取当前集合的迭代器Iterator<String> it = lists.iterator();2.定义一个while循环,问一次取一次。通过it.hasNext()询问是否有下一个元素,有就通过it.next()取出下一个元素。小结:记住代码。*/
public class CollectionDemo01 {public static void main(String[] args) {ArrayList<String> lists = new ArrayList<>();lists.add("赵敏");lists.add("小昭");lists.add("素素");lists.add("灭绝");System.out.println(lists);// [赵敏, 小昭, 素素, 灭绝]//   it// 1、得到当前集合的迭代器对象。Iterator<String> it = lists.iterator();//注释掉的这部分如果打开直接就遍历完了,下面的循环就没有用了/*String ele = it.next();System.out.println(ele);System.out.println(it.next());System.out.println(it.next());System.out.println(it.next());// System.out.println(it.next()); // NoSuchElementException 出现无此元素异常的错误*/// 2、定义while循环while (it.hasNext()){String ele = it.next();System.out.println(ele);//System.out.println(it.next());//不要在一个里面取两次,如果只有 [赵敏, 小昭, 素素] 这样运行的话就会崩溃}}
}

默认位置在Iterator<E> iterator():得到迭代器对象,默认指向当前集合的索引0

迭代器如果取元素越界会出现NoSuchElementException异常。

2]方式二:foreach/增强for循环

 

3]方式三:lambda表达式

package com.itheima.d3_collection_traversal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;public class CollectionDemo03 {public static void main(String[] args) {Collection<String> lists = new ArrayList<>();lists.add("赵敏");lists.add("小昭");lists.add("殷素素");lists.add("周芷若");System.out.println(lists);// [赵敏, 小昭, 殷素素, 周芷若]//  slists.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});//        lists.forEach(s -> {
//                System.out.println(s);
//        });// lists.forEach(s ->  System.out.println(s) );lists.forEach(System.out::println );}
}

5)集合存储自定义类型的对象

6)常见数据结构

1]数据结构概述、栈、队列

数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。

通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率

常用的数据结构栈、队列、数组、链表、二叉树、二叉查找树、平衡二叉树、红黑树

2]数组

数组是一种查询快(根据索引查),增删慢的模型

查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)

删除效率低:要将原始数据删除,同时后面每个数据前移。

添加效率极低:添加位置后的每个数据后移,再添加元素。

3]链表

链表中的元素是游离存储的,每个元素节点包含数据值和下一个元素的地址。

链表查询慢。无论查询哪个数据都要从头开始找

链表增删相对快(找位置的时候是慢的,但是增删的那一段时间是快的,增删首尾的时候是最快的)

4]二叉树、 二叉查找树

(增删改查都比较快的数据结构)

5]平衡二叉树

6]红黑树

①概述:(红黑树增删改查的性能都很好)

红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构。

1972年出现,当时被称之为平衡二叉B树。1978年被修改为如今的"红黑树"。

每一个节点可以是红或者黑;红黑树不是通过高度平衡的,它的平衡是通过“红黑规则”进行实现的。

②红黑规则:(红黑树不是高度平衡的,它的平衡是通过"红黑规则"进行实现的)

每一个节点或是红色的,或者是黑色的,根节点必须是黑色。

如果一个节点没有子节点或者父节点,则该节点相应俄指针属性值为Nil,这些Nil视为叶节点,叶节点为黑色的。

如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连的情况)。

对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

7]各种数据结构的特点和作用是什么样的

队列:先进先出,后进后出。(数据从后端进入队列模型的过程称为:入队列;数据从前端离开队列模型的过程称为:出队列)

:后进先出,先进后出。(数据进入栈模型的过程称为:压栈/进栈;数据离开栈模型的过程称为:弹栈/出栈)

数组:内存连续区域,查询快(根据索引定位元素快),增删慢。

链表:元素是游离的,查询慢(有索引,但是也很慢,要一个一个查),首尾操作极快(双向链表)。

二叉树:永远只有一个根节点, 每个结点不超过2个子节点的树。

查找二叉树:小的左边,大的右边,但是可能树很高,查询性能变差。

平衡查找二叉树:让树的高度差不大于1,增删改查都提高了。

红黑树:(就是基于红黑规则实现了自平衡的排序二叉树)

7)List系列集合

1]List集合特点、特有API

List集合继承了Collection集合的全部功能,"同时因为List系列集合有索引",

因为List集合多了索引,所以多了很多按照索引操作元素的功能

ArrayList、LinekdList :有序(存储和取出的元素顺序一致),可重复(存储的元素可以重复),有索引(可以通过索引操作元素)。

List的实现类的底层原理

ArrayList底层是基于数组实现的,根据查询元素快,增删相对慢。

LinkedList底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的。

2]List集合的遍历方式小结

迭代器             增强for循环           Lambda表达式       for循环(因为List集合存在索引)

3]ArrayList集合的底层原理

4]LinkedList集合的底层原理

LinkedList可以完成队列结构和栈结构(双链表)

8)补充知识:集合的并发修改异常问题

package com.itheima.d6_collection_update_delete;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;//目标:研究集合遍历并删除元素可能出现的:并发修改异常问题。
public class Test {public static void main(String[] args) {// 1、准备数据ArrayList<String> list = new ArrayList<>();list.add("黑马");list.add("Java");list.add("Java");list.add("赵敏");list.add("赵敏");list.add("素素");System.out.println(list);// [黑马, Java, Java, 赵敏, 赵敏, 素素]//        it// 需求:删除全部的Java信息。// a、迭代器遍历删除/*Iterator<String> it = list.iterator();while (it.hasNext()){String ele = it.next();if("Java".equals(ele)){// 删除Java// list.remove(ele); // 集合删除会出毛病,第一个java删掉后it.remove(); // 删除迭代器所在位置的元素值(没毛病)}}System.out.println(list);*///b、foreach遍历删除 (会出现问题[并发修改异常],这种无法解决的,foreach不能边遍历边删除,会出bug)/*for (String s : list) {if("Java".equals(s)){list.remove(s);}}*/// c、lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug)/*list.forEach(s -> {if("Java".equals(s)){list.remove(s);}});*/// d、for循环(边遍历边删除集合没毛病,但是必须从后面开始遍历删除才不会出现漏掉应该删除的元素)//for (int i = 0; i < list.size(); i++) {//正着是不行的for (int i = list.size() - 1; i >= 0 ; i--) {String ele = list.get(i);if("Java".equals(ele)){list.remove(ele);}}//解决方案2(和迭代器的想法是差不多的)/*for (int i = 0; i < list.size(); i++) {String ele = list.get(i);if("Java".equals(ele)){list.remove(ele);i--}}*/System.out.println(list);}
}

9)补充知识:泛型深入

1]泛型的概述和优势

概述

泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。

泛型的格式:<数据类型>; 注意:泛型只能支持引用数据类型。

集合体系的全部接口和实现类都是支持泛型的使用的。

优势

统一数据类型。

把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来。

泛型可以在很多地方进行定义:

类后面                                 ----->                            泛型类

方法申明上                         ----->                            泛型方法

接口后面                             ----->                            泛型接口

2]自定义泛型类

定义类时同时定义了泛型的类就是泛型类。

格式:修饰符 class 类名<泛型变量>{ }               范例:public class MyArrayList<T> { }

此处泛型变量T可以随便写为任意标识,常见的如E、T、K、V等。

作用:编译阶段可以指定数据类型,类似于集合的作用。

原理(核心思想):把出现泛型变量的地方全部替换成传输的真实数据类型。

package com.itheima.d8_genericity_class;import java.util.ArrayList;public class MyArrayList<E> {private ArrayList lists = new ArrayList();public void add(E e){lists.add(e);}public void remove(E e){lists.remove(e);}@Overridepublic String toString() {return lists.toString();}
}
//————————————————————————————————————————————————————
package com.itheima.d8_genericity_class;public class Test {public static void main(String[] args) {// 需求:模拟ArrayList定义一个MyArrayList ,关注泛型设计MyArrayList<String> list = new MyArrayList<>();list.add("Java");list.add("Java");list.add("MySQL");list.remove("MySQL");System.out.println(list);MyArrayList<Integer> list2 = new MyArrayList<>();list2.add(23);list2.add(24);list2.add(25);list2.remove(25);System.out.println(list2);}
}

3]自定义泛型方法

定义方法时同时定义了泛型的方法就是泛型方法。

泛型方法的格式:修饰符 <泛型变量> 方法返回值 方法名称(形参列表){}

范例: public <T> void show(T t) {  }

作用:方法中可以使用泛型接收一切实际类型的参数,方法更具备通用性。

原理(核心思想):把出现泛型变量的地方全部替换成传输的真实数据类型。

package com.itheima.d9_genericity_method;/**目标:自定义泛型方法。什么是泛型方法?定义了泛型的方法就是泛型方法。泛型方法的定义格式:修饰符 <泛型变量> 返回值类型 方法名称(形参列表){}注意:方法定义了是什么泛型变量,后面就只能用什么泛型变量。泛型类的核心思想:是把出现泛型变量的地方全部替换成传输的真实数据类型。需求:给你任何一个类型的数组,都能返回它的内容。Arrays.toString(数组)的功能!小结:泛型方法可以让方法更灵活的接收数据,可以做通用技术!*/
public class GenericDemo {public static void main(String[] args) {String[] names = {"小璐", "蓉容", "小何"};printArray(names);Integer[] ages = {10, 20, 30};printArray(ages);Integer[] ages2 = getArr(ages);String[]  names2 = getArr(names);}public static <T> T[] getArr(T[] arr){return arr;}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);}}
}

4]自定义泛型接口

使用了泛型定义的接口就是泛型接口。

格式:修饰符 interface 接口名称<泛型变量>{}         范例: public interface Data<E>{}

作用:泛型接口可以让实现类选择当前功能需要操作的数据类型。(泛型接口可以约束实现类,实现类可以在实现接口的时候传入自己操作的数据类型这样重写的方法都将是针对于该类型的操作。)

课程案例导学:教务系统,提供一个接口可约束一定要完成数据(学生,老师)的增删改查操作

原理:实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都将是针对于该类型的操作。

//重点关注语法
package com.itheima.d10_genericity_interface;/**目标:泛型接口。什么是泛型接口?使用了泛型定义的接口就是泛型接口。泛型接口的格式:修饰符 interface 接口名称<泛型变量>{}需求: 教务系统,提供一个接口可约束一定要完成数据(学生,老师)的增删改查操作小结:泛型接口可以约束实现类,实现类可以在实现接口的时候传入自己操作的数据类型这样重写的方法都将是针对于该类型的操作。*/
public class GenericDemo {public static void main(String[] args) {}
}
//——————————————————————————————————————————————
package com.itheima.d10_genericity_interface;public interface Data<E> {void add(E e);void delete(int id);void update(E e);E queryById(int id);
}
//——————————只是讲语法里面内容不写—————————————————
package com.itheima.d10_genericity_interface;
public class Student {//如果这么写,在写接口的时候,就要实现void add(Student s);这种写法,不具备通用性,所以要采用泛型接口
}
//——————————只是讲语法里面内容不写——————————————————
package com.itheima.d10_genericity_interface;
public class Teacher {
}
//——————————泛型接口具体使用————————————————————————————————
package com.itheima.d10_genericity_interface;
public class StudentData implements Data<Student>{@Overridepublic void add(Student student) { }@Overridepublic void delete(int id) { }@Overridepublic void update(Student student) { }@Overridepublic Student queryById(int id) {return null;}
}
//——————————泛型接口具体使用————————————————————————————————
package com.itheima.d10_genericity_interface;
public class TeacherData implements Data<Teacher>{@Overridepublic void add(Teacher teacher) { }@Overridepublic void delete(int id) { }@Overridepublic void update(Teacher teacher) { }@Overridepublic Teacher queryById(int id) {return null;}
}

5]泛型通配符、上下限

通配符? 可以在“使用泛型”的时候代表一切类型。E T K V 是在定义泛型的时候使用的。

package com.itheima.d11_genericity_limit;import java.util.ArrayList;
/**目标:泛型通配符。?需求:开发一个极品飞车的游戏,所有的汽车都能一起参与比赛。注意:!!!!!!虽然BMW和BENZ都继承了Car但是ArrayList<BMW>和ArrayList<BENZ>与ArrayList<Car>没有关系的!!通配符:??可以在“使用泛型”的时候代表一切类型。E T K V 是在定义泛型的时候使用的。泛型的上下限:? extends Car : ?必须是Car或者其子类  泛型上限? super Car :?必须是Car或者其父类   泛型下限(用得少)小结:通配符:??可以在“使用泛型”的时候代表一切类型。*/
public class GenericDemo {public static void main(String[] args) {ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);ArrayList<BENZ> benzs = new ArrayList<>();benzs.add(new BENZ());benzs.add(new BENZ());benzs.add(new BENZ());go(benzs);ArrayList<Dog> dogs = new ArrayList<>();dogs.add(new Dog());dogs.add(new Dog());dogs.add(new Dog());// go(dogs);}/**所有车比赛*///public static void go(ArrayList<BMW> cars){ }//这样写的话,BENZ就进不来了public static void go(ArrayList<? extends Car> cars){ }
}class Dog{ } //public static void go(ArrayList<?> cars){ }//?这种写法的话,代表了一切类型,狗也可以参加比赛了,所以不能这么写class BENZ extends Car{ }
class BMW extends Car{ }
// 父类
class Car{ }

22.Set系列集合

1)Set系列集系概述

1] Set系列集合特点

无序:存取顺序不一致(只会无序一次,不是随机无序,当第一次无序之后,以后都是按照这个顺序)

不重复:可以去除重复

无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。

2] Set集合实现类特点

HashSet : 无序、不重复、无索引。

LinkedHashSet:有序(先加的在前面,后加的在后面)、不重复、无索引。

TreeSet:可排序(天然的对元素进行大小升序的排序)、不重复、无索引。

Set集合的功能上基本上与Collection的API一致

2)HashSet元素无序的底层原理:哈希表

1] HashSet集合底层采取哈希表存储的数据。

2] 哈希表是一种对于增删改查数据性能都较好的结构。

3] 哈希表的组成

JDK8之前的,底层使用数组+链表组成

JDK8开始后,底层采用数组+链表+红黑树组成。

4]哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数值。(所谓的地址,不是真正的地址)

5] Object类的API:public int hashCode​():返回对象的哈希值

6] 对象的哈希值特点

同一个对象多次调用hashCode()方法返回的哈希值是相同的

默认情况下,不同对象的哈希值是不同的。

7] 哈希表的详细流程

①创建一个默认长度16,默认加载因为0.75的数组,数组名table

②根据元素的哈希值跟数组的长度计算出应存入的位置(哈希算法)

③判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组。(JDK 7新元素占老元素位置,指向老元素;JDK 8中新元素挂在老元素下面)

④当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍

8]  JDK1.8版本开始HashSet原理解析

底层结构:哈希表(数组、链表、红黑树的结合体)

当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树。

结论:JDK8开始后,哈希表对于红黑树的引入进一步提高了操作数据的性能。

3)HashSet元素去重复的底层原理

package com.itheima.d1_collection_set;import java.util.Objects;public class Student {private String name;private int age;private char sex;public Student() {}public Student(String name, int age, char sex) {this.name = name;this.age = age;this.sex = sex;}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 char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}/**只要2个对象内容一样,结果一定是true* @param o* @return*/@Overridepublic 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 && sex == student.sex && Objects.equals(name, student.name);}/**s1 = new Student("无恙", 20, '男')s2 = new Student("无恙", 20, '男')s3 = new Student("周雄", 21, '男')*/@Overridepublic int hashCode() {return Objects.hash(name, age, sex);}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", sex=" + sex +'}';}
}
//——————————————————————————————————————————————————
package com.itheima.d1_collection_set;import java.util.HashSet;
import java.util.Set;//目标:让Set集合把重复内容的对象去掉一个(去重复)
public class SetDemo3 {public static void main(String[] args) {// Set集合去重复原因:先判断哈希值算出来的存储位置是否相同 再判断equalsSet<Student> sets = new HashSet<>();Student s1 = new Student("无恙", 20, '男');Student s2 = new Student("无恙", 20, '男');Student s3 = new Student("周雄", 21, '男');System.out.println(s1.hashCode());System.out.println(s2.hashCode());System.out.println(s3.hashCode());sets.add(s1);sets.add(s2);sets.add(s3);System.out.println(sets);}
}
/*如果希望Set集合认为2个内容相同的对象是重复的应该怎么办?          重写对象的hashCode和equals方法。 */

4)实现类:LinkedHashSet

特点:

有序、不重复、无索引。

这里的有序指的是保证存储和取出的元素顺序一致

原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序。

5)实现类:TreeSet

1] 特点

不重复、无索引、可排序

可排序:按照元素的大小默认升序(有小到大)排序。

TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好。

注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序。

2] 集合默认的规则

对于数值类型:Integer , Double,官方默认按照大小进行升序排序。

对于字符串类型:默认按照首字符的编号升序排序。

对于自定义类型如Student对象,TreeSet无法直接排序。

结论:想要使用TreeSet存储自定义类型,需要制定排序规则

3] 自定义排序规则

TreeSet集合存储对象的的时候有2种方式可以设计自定义比较规则

方式一:让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。(类实现Comparable接口,重写比较规则)

方式二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。(集合自定义Comparator比较器对象,重写比较规则。)

两种方式中,关于返回值的规则:

如果认为第一个元素大于第二个元素返回正整数即可。

如果认为第一个元素小于第二个元素返回负整数即可。

如果认为第一个元素等于第二个元素返回0即可,此时Treeset集合只会保留一个元素,认为两者重复。

注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序。

package com.itheima.d1_collection_set;public class Apple implements Comparable<Apple>{private String name;private String color;private double price;private int weight;public Apple() { }public Apple(String name, String color, double price, int weight) {this.name = name;this.color = color;this.price = price;this.weight = weight;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}@Overridepublic String toString() {return "Apple{" +"name='" + name + '\'' +", color='" + color + '\'' +", price=" + price +", weight=" + weight +'}';}//方式一:类自定义比较规则o1.compareTo(o2)@Overridepublic int compareTo(Apple o) {// 按照重量进行比较的return this.weight - o.weight ; // 去重重量重复的元素// return this.weight - o.weight >= 0 ? 1 : -1; // 保留重量重复的元素}
}
//——————————————————————————————————————————————————————————
package com.itheima.d1_collection_set;import java.util.Set;
import java.util.TreeSet;/**目标:观察TreeSet对于有值特性的数据如何排序。学会对自定义类型的对象进行指定规则排序*/
public class SetDemo5 {public static void main(String[] args) {//注意:如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序。//方式一/*Set<Apple> apples = new TreeSet<>();apples.add(new Apple("红富士", "红色", 9.9, 500));apples.add(new Apple("青苹果", "绿色", 15.9, 300));apples.add(new Apple("绿苹果", "青色", 29.9, 400));apples.add(new Apple("黄苹果", "黄色", 9.8, 500));System.out.println(apples); */// 方式二:集合自带比较器对象进行规则定制/*Set<Apple> apples = new TreeSet<>(new Comparator<Apple>() {@Overridepublic int compare(Apple o1, Apple o2) {// return o1.getWeight() - o2.getWeight(); // 升序// return o2.getWeight() - o1.getWeight(); // 降序// 注意:浮点型建议直接使用Double.compare进行比较// return Double.compare(o1.getPrice() , o2.getPrice()); // 升序return Double.compare(o2.getPrice() , o1.getPrice()); // 降序}});*///代码简化,lambda表达式Set<Apple> apples = new TreeSet<>(( o1,  o2) ->  Double.compare(o2.getPrice() , o1.getPrice())  );apples.add(new Apple("红富士", "红色", 9.9, 500));apples.add(new Apple("青苹果", "绿色", 15.9, 300));apples.add(new Apple("绿苹果", "青色", 29.9, 400));apples.add(new Apple("黄苹果", "黄色", 9.8, 500));System.out.println(apples);}
}

23.Collection体系的特点、使用场景总结

24.补充知识:可变参数

package com.itheima.d2_params;import java.util.Arrays;/**目标:可变参数。可变参数用在形参中可以接收多个数据。可变参数的格式:数据类型...参数名称可变参数的作用:传输参数非常灵活,方便。可以不传输参数。可以传输一个参数。可以传输多个参数。可以传输一个数组。可变参数在方法内部本质上就是一个数组。可变参数的注意事项:1.一个形参列表中可变参数只能有一个!!2.可变参数必须放在形参列表的最后面!!小结:记住。*/
public class MethodDemo {public static void main(String[] args) {sum(); // 1、不传参数sum(10); // 2、可以传输一个参数sum(10, 20, 30); // 3、可以传输多个参数sum(new int[]{10, 20, 30, 40, 50}); // 4、可以传输一个数组}/**注意:一个形参列表中只能有一个可变参数,可变参数必须放在形参列表的最后面* @param nums*///public static void sum(int...nums,int...nums2 ){这样写是不行的//public static void sum(int age,int...nums ){这样写是可以的public static void sum(int...nums){// 注意:可变参数在方法内部其实就是一个数组。 numsSystem.out.println("元素个数:" + nums.length);System.out.println("元素内容:" + Arrays.toString(nums));}
}

25.补充知识:集合工具类Collections

package com.itheima.d3_collections;import java.util.*;
/**目标:Collections工具类的使用。java.utils.Collections:是集合工具类Collections并不属于集合,是用来操作集合的工具类。Collections有几个常用的API:- public static <T> boolean addAll(Collection<? super T> c, T... elements)     给集合对象批量添加元素!- public static void shuffle(List<?> list) :       打乱集合顺序。· collections排序相关API,使用范围:只能对于List集合的排序- public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。(注意:本方式不可以直接对自定义类型的List集合排序,除非自定义类型实现了比较规则Comparable)- public static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序。*/
public class CollectionsDemo01 {public static void main(String[] args) {List<String> names = new ArrayList<>();//names.add("楚留香");//names.add("胡铁花");//names.add("张无忌");//names.add("陆小凤");Collections.addAll(names, "楚留香","胡铁花", "张无忌","陆小凤");System.out.println(names);// 2、public static void shuffle(List<?> list) :打乱集合顺序。//(只打乱list顺序,list是基于数组的,一个萝卜一个坑,调换一下是不影响的   不打乱set顺序,因为set本来就是无序的,但是按照自己hash值的标准来定义)Collections.shuffle(names);System.out.println(names);// 3、 public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。 (排 值特性的元素)List<Integer> list = new ArrayList<>();Collections.addAll(list, 12, 23, 2, 4);System.out.println(list);Collections.sort(list);System.out.println(list);}
}
package com.itheima.d3_collections;public class Apple implements Comparable<Apple>{private String name;private String color;private double price;private int weight;public Apple() {}public Apple(String name, String color, double price, int weight) {this.name = name;this.color = color;this.price = price;this.weight = weight;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getWeight() {return weight;}public void setWeight(int weight) {this.weight = weight;}@Overridepublic String toString() {return "Apple{" +"name='" + name + '\'' +", color='" + color + '\'' +", price=" + price +", weight=" + weight +'}';}//方式一:类自定义比较规则o1.compareTo(o2)@Overridepublic int compareTo(Apple o) {// 按照重量进行比较的return this.weight - o.weight ; // List集存储相同大小的元素 会保留!}
}
//————————————————————————————————————————————————————————————————————
package com.itheima.d3_collections;import java.util.*;
/**目标:引用数据类型的排序。字符串按照首字符的编号升序排序!自定义类型的比较方法API:Collections- public static <T> void sort(List<T> list):将集合中元素按照默认规则排序。对于自定义的引用类型的排序人家根本不知道怎么排,直接报错!- public static <T> void sort(List<T> list,Comparator<? super T> c):将集合中元素按照指定规则排序,自带比较器*/
public class CollectionsDemo02 {public static void main(String[] args) {List<Apple> apples = new ArrayList<>(); // 可以重复!apples.add(new Apple("红富士", "红色", 9.9, 500));apples.add(new Apple("青苹果", "绿色", 15.9, 300));apples.add(new Apple("绿苹果", "青色", 29.9, 400));apples.add(new Apple("黄苹果", "黄色", 9.8, 500));// 方法一:可以的,Apple类已经重写了比较规则/*Collections.sort(apples);System.out.println(apples);*/// 方式二:sort方法自带比较器对象/*Collections.sort(apples, new Comparator<Apple>() {@Overridepublic int compare(Apple o1, Apple o2) {return Double.compare(o1.getPrice() , o2.getPrice()); // 按照价格排序!!}});*/Collections.sort(apples, ( o1,  o2) ->  Double.compare(o1.getPrice() , o2.getPrice()) );System.out.println(apples);}
}

26.Collection体系的综合案例

package com.itheima.d4_collection_test;public class Card {private String size;private String color;private int index; // 牌的真正大小public Card(){ }public Card(String size, String color, int index) {this.size = size;this.color = color;this.index = index;}public String getSize() {return size;}public void setSize(String size) {this.size = size;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}@Overridepublic String toString() {return size + color;}
}
//——————————————————————————————————————————
package com.itheima.d4_collection_test;import java.util.*;/**目标:斗地主游戏的案例开发。业务需求分析:斗地主的做牌, 洗牌, 发牌, 排序(拓展知识), 看牌。业务: 总共有54张牌。点数: "3","4","5","6","7","8","9","10","J","Q","K","A","2"花色: "♠", "♥", "♣", "♦"大小王: "												

java基础,进阶(二)相关推荐

  1. Java校招笔试题-Java基础部分(二)

    导语   Java面试题集2021版 Java基础部分二 14.hashCode方法的作用? 15.写clone()方法时,通常都有一行代码,这行代码是什么? 16.静态变量和实例变量的区别? 17. ...

  2. Java实习生常规技术面试题每日十题Java基础(二)

    目录 1. JAVA 的反射机制的原理. 2.静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同? 3.如何将String类型转化成Number类型. 4.什 ...

  3. 第二十八节:Java基础-进阶继承,抽象类,接口

    前言 Java基础 - 进阶继承,抽象类,接口 进阶继承 class Stu {int age = 1; } class Stuo extends Stu {int agee = 2; } class ...

  4. Java基础(二):集合、IO流(Zip压缩输入/输出流等)、File文件类、反射、枚举

    Java基础(一):编译和解释.数据类型.变量作用域.String常用方法.数组.面向对象.异常 Java基础(二):集合.IO流(Zip压缩输入/输出流等).File文件类.反射.枚举 Java异常 ...

  5. 深入Java基础(二)——字符串家族

    上一篇写了基本数据类及其包装类详解,这篇我们就来讨字符串这个家族吧,这个也是重中之重啊!!! 文章结构: 1.众说纷纷的equals和==: 2.字符串家族的基本知识以及字符串家族的源码解读: 3.字 ...

  6. 分享 java 基础 + 进阶精简资料(视频 + 源码 + 就业项目 + 面试报装)

    前言 有些同学可能会觉得奇怪,为什么会写这么一篇文章,Java 基础不是大学就学过了吗,就这呀,这有什么好写的? 但是从事开发越久才越知道基础有多重要,不止 Java 基础,还有计算机网络基础与操作系 ...

  7. 第一阶段>>>Java基础进阶 OOP/Reflect/注解/IO流/API核心

    目录 >>>java基础01-结构以及类型 >>>java基础02-初识数组 >>>java基础03-面向对象OOP >>>ja ...

  8. Java基础系列二:Java泛型

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.泛型概述 1.定 ...

  9. java基础总结二--让大学生活不再迷茫

    承接我的上一篇博客java基础总结1 https://blog.csdn.net/weixin_43410352/article/details/87073372 10.java的三大特性 封装:这是 ...

  10. Java基础知识(二) 面向对象的技术

    Java基础知识 面向对象的技术 1. 面向对象与面向过程有什么区别 2. 面向对象有哪些特征 3. 什么是继承 4. 组合和继承的区别 5. 多态的实现机制 6. 重载和覆盖有什么区别 7. 抽象类 ...

最新文章

  1. 3、常用数据库访问接口简介
  2. 在控制台输出口,根据内存地址,找到被过度释放的对象!
  3. 【蓝桥杯Java_C组·从零开始卷】第八节、集合——list详解
  4. Python小游戏(并夕夕版飞机大战)
  5. 车牌识别与计算机编程,基于MATLAB的车牌识别程序详解.ppt
  6. centos7 网卡配置vlan_CentOS7网卡创建vlan步骤
  7. 周期性/定时执行python任务,使用三种方法:while、apscheduler、sched
  8. 拒绝礼仪与技巧(转)
  9. 广西科技大学计算机考研,广西科技大学研究生院
  10. (顺序表的应用5.4.2)POJ 1591 M*A*S*H(约瑟夫环问题的变形——变换步长值)
  11. 快播CEO认罪,成人网站对技术的要求有多高?
  12. 【python 色情图片识别】python检测色情图片
  13. 神经元的结构是?包括髓鞘吗?|小白心理-347/312考研答疑
  14. ensp MSTP实验搭建
  15. 抖客联盟API如何申请?
  16. Oracle启动错误:ORA-00821: Specified value of sga_target 2352M is too small, needs to be at least 4352M
  17. 外语学习应试教育时如何高效的背单词?
  18. Jmeter测试结果导出指南
  19. 模电(六)放大电路分析二
  20. AE教程_时光流逝看我七十二变

热门文章

  1. 数据结构:按成绩输出名次排序
  2. 静态分析android程序之阅读smali代码
  3. iframe框架下的子父级页面监控页面关闭事件
  4. 屌丝码农该怎么过周末
  5. 中国移动CMPP协议、联通SGIP协议、电信SMGP协议短信网关
  6. Python全年天数查询源代码
  7. 基于LabVIEW的计时器
  8. 比对软件Blast,Blast+,Diamond如何选
  9. python 创建高维数组列表
  10. PDF如何解密?这些方法你知道吗?