1-时间API
JDK8之后
对时间类进行了优化更新,使用起来更方便,更舒服
8版本前后对比
8版本后:
设计更合理,功能丰富,使用更方便。
都是不可变对象,修改后会返回新的时间对象,不会娈失最开始的时间。
线程安全。
能精确到毫秒、纳秒。
8版本前:
设计欠妥,使用不方便,很多都被淘汰了。
都是可变对象,修改后会丢失最开始的时间信息。
线程不安全。
只能精确到毫秒。
LocalDate
:年、月、日
LocalTime
:时、分、秒
LocalDateTime
:年、月、日、时、分、秒
ZoneId
:时区
ZonedDateTime
:带时区的时间
Instant
:时间戳/时间线
DateTimeFormatter
:用于时间的格式化和解析
Duration
:时间间隔(时、分、秒,纳秒)
Period
:时间间隔(年,月,日)
日历类LocalDateTime
LocalDate:代表本地日期(年、月、日、星期)
LocalTime:代表本地时间(时、分、秒、纳秒)
LocalDateTime:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)
对象的创建方式
用LocalDateTime中的now()
;或者of();
方法
注意对象创建后不可修改,一定要进行接收。
.now(); 当前时间
.of(); 设置时间
package com.lyl.jdk8;
import java.time.LocalDateTime;
public class Demo {
public static void main(String[] args) {
//获取此刻的时间对象
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
//获取指定的时间对象
LocalDateTime of = LocalDateTime.of(2008,8,22,11,30,28);
System.out.println(of);
}
}
获取年/月/日/时/分/秒:对应的对象名.getXXX方法
注意:getMonth();getDayOfWeek;
返回的是对应的对象(例如:MARCH),想转换成数字可以用getValue();
方法
修改年月日时分秒相关的方法
LocalDateTime、LocalDate、LocalTime都是不可变的,下列方法返回的是一个新的对象
minus:减
plus:加
with:设置(每次只能改一个值)
总结
LocalDate LocalTime LocalDateTime对象如何创建?
now:当前时间
of:指定时间
2.获取的相关方法是?
getXxx();
getYear()getMonth()getMonthValue()...
3.修改的相关方法是?
withXxx:修改
minusXxx:减
plusXxx:加
4.注意点:
LocalDateTime、LocalDate、LocalTime都是不可变的 调用修改的相关方法,返回的都是新的对象
日期格式化类DateTimeFormatter
用于时间的格式化和解析(替代SimpleDateFormatter)
对象的创建方式
调用DateTimeFormatter类中的.ofPattern("格式");方法
package com.lyl.jdk8;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateTimeFormatterDemo {
public static void main(String[] args) {
//创建当前时间对象
LocalDateTime nowTime = LocalDateTime.now();
//创建用于格式化和解析的对象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年M月d日");
//格式化
String format = dtf.format(nowTime);
System.out.println(format);
//解析 因为只有年月日,所以用LocalDate
LocalDate localDate = LocalDate.parse(format,dtf);
System.out.println(localDate);
}
}
注意:定义格式中俩MM和俩dd改成单M和单d
时间类
.now();获取当前时间
.atZone("时区");获取指定时区时间(做国外业务需要使用)
注意:亚洲中国只有上海、重庆
ZoneId类(时区类)
Instant时间戳
-
用于表示时间的对象,类似之前所学习的Date
ZoneDateTime类(带时区)
思路
-
确定业务环境
-
国外考虑时区,用ZoneId
-
国内用LocalDateTime
工具类
Period类
Period.between创建对象
用于计算两个“日期”间隔(年、月、日)
Duration类
Duration.between创建对象
用于计算两个“时间”间隔(秒,纳秒)
ChronoUnit类
用于计算两个“日期”间隔
ChronoUnit.静态年/月 /日等等.between(时间1,时间2):时间2-时间1
练习
计算时间间隔
package com.lyl.test;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class BirthdayTest {
public static void main(String[] args) {
//1.创建当前时间对象
LocalDate localDate = LocalDate.now();
//2.创建生日时间对象
LocalDate birthday = LocalDate.of(2001,10,11);
//3.计算时间间隔(年)
long result = ChronoUnit.YEARS.between(birthday, localDate);
System.out.println(result);
}
}
输出结果:21
2-集合
集合分为单列集合和双列集合
-
Collection单列集合,每个元素(数据)只包含一个值。
-
Map双列集合,每个元素包含两个值(键值对)。
Collection集合体系
描述:不同的集合,底层的数据结构不同,适用的场景也不同
目标:能够独立分析需求,选对合适的集合
-
List接口:存取有序,有索引,可以存储重复的
ArrayList类:底层是数组实现(查询和修改快,增删慢)
LinkedList类:底层是链表实现(查询和修改慢,增删相对较快,首尾操作极快)
-
Set接口:存取无序,没有索引,不能存储重复的
TreeSet:底层是红黑树结构
HashSet:底层是哈希表结构
LinkedHashSet:底层哈希表+双向链表
-
Collection是单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的。
Collection API
迭代器遍历
-
遍历就是一个一个的把容器中的元素访问一遍。
-
迭代器在到ava中的代表是
Iterator
,迭代器是集合的专用遍历方式。
-
获取迭代器
Iterator<Student> it = c.iterator();
接口的引用=实现类的对象
-
循环判断集合中是否还有元素
while(it.hasNext())
-
调用next方法取出元素
sout.(it.next());
迭代器源码执行流程
增强for循环
JDK5版本之后出现的一种迭代器的语法糖,底层也是一个迭代器
-
既可以遍历集合也可以遍历数组。
-
它是JDK5之后出现的,其内部原理是一个teratori迭代器,遍历集合相当于是迭代器的简化写法。
-
实现Iterable接口的类才可以使用迭代器和增强for,Collection接口已经继承了Iterable接口。
格式:
for(元素数据类型 变量名 : 数组或者Collection集合) {
//在此处使用变量即可,该变量就是元素
}
Lambda表达式遍历集合
Collection结合Lambda遍历的API
匿名内部类:
Collection<String> lists = new ArrayList<>();
...
lists.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
转换为Lambda表达式:
lists.forEach(s -> {System.out.println(s);
});
// lists.forEach(s -> System.out.println(s));
练习:影片信息在程序中的表示
需求:某影院系统需要在后台存储上述三部电影,然后依次展示出来
属性:电影名name 评分score 主演acotr
package com.lyl.test;
import com.lyl.domain.Movie;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class MovieTest {
public static void main(String[] args) {
Collection<Movie> c = new ArrayList<>();
c.add(new Movie("肖申克救赎",9.7,"蒂姆罗宾斯"));
c.add(new Movie("霸王别姬",9.6,"张国荣"));
c.add(new Movie("阿甘正传",9.5,"汤姆汉克斯"));
//1、迭代器遍历
Iterator<Movie> iterator = c.iterator();
while (iterator.hasNext()){
Movie next = iterator.next();
System.out.println(next);
}
//2、增强for循环遍历
for (Movie movie : c) {
System.out.println(movie);
}
//3、forEach遍历
c.forEach(movie -> System.out.println(movie));
}
}
数据结构
概述
-
数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。
-
通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
栈
-
后进先出,先进后出
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
队列
-
先进先出,后进后出
数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
数组
-
查询速度快:查询数据通过地址值和索引定位,查询任意数据耗时相同。(元素在内存中是连续存储的)
-
删除效率低:要将原始数据删除,同时后面每个数据前移
-
添加效率极低:添加位置后的每个数据后移,再添加元素。
数组是一种查询快,增删慢的模型
链表
-
链表中的元素是在内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址
-
链表查询慢,无论查询哪个数据都要从头开始找(单链表)
-
链表增删相对快
-
单链表:查询的时候,只能从头开始找
-
双链表:查询的时候,可以从头找也可以从尾找
单向链表:每一个节点,记录下一个节点的地址
双向链表:每一个节点,记录下一个节点的地址的同时,还记录上一个节点的地址
-
List的实现类的底层原理
-
List集合因为支持索引,所以多了很多索引操作的独特api,其他Collection的功能List也都继承了。
-
List派系下面的集合,多了一种遍历方式,可以使用普通for循环进行遍历(因为它有索引)
ArrayList底层是基于数组实现的:根据索引定位元素快,增删相对慢。
LinkedList底层基于双链表实现的:查询元素慢,增删首尾元素是非常快的。
ArrayList 长度可变原理
-
底层源码执行流程
创建集合对象时,集合默认为空,只有调用add方法时才会创建一个长度为10的数组,当满后继续添加元素,扩容1.5倍长度
LinkedList的特点
-
底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。
细节:
List.get(i):表面来看是根据索引获取元素,但是这个集合是LinkedList,底层是链表结构,找元素的时候:
1.判断你要查找的元素,离头部近,还是离尾部近
2,离头部近:从头开始查找(正序遍历)
3.离尾部近:从尾开始查找(倒序遍历)
代码目标:
1,集合会创建,数据会添加
2,能够进行赠删改查
3,掌握List集合的4中遍历方式(迭代器,增强for,forEach,普通for)
并发修改异常
迭代器遍历集合的时候,使用集合对象,调用添加或删除,修改的方法,操作集合中的元素,就会出现并发修改异常
-
(迭代器,集合对象)在并发操作
解决方案:
-
迭代器在遍历的时候,使用迭代器自己的删除方法
细节:如果使用集合对象,删除的是倒数第二个元素,就不会出现并发修改异常
结论:逃过了编译期的异常检查
集合在遍历的过程中进行删除操作:
1.迭代器
-
不需要手动i--操作,源码中自动做了这件事情
2.增强for
-
不能删除
3.forEach
-
不能删除
4.普通for
A:正序遍历,索引--
B:倒序遍历