学习计划
JDK8新增时间类
JDK7计算时间比较需要先转化成毫秒值,计算复杂,多线程环境下会导致数据安全的问题,JDK8时间日期对象都是不可变的,解决了这个问题。
1. 时区,时间和格式化
1.1 Date类
ZoneId
获取时区。
// 获取所有的时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds.size());
System.out.println(zoneIds);
//获取系统时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);
//获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Chongqing");
System.out.println(zoneId1);
Instant时间戳
//获取当前时间的Instant对象(标准时间)
Instant n = Instant.now();
System.out.println(n);
//ofXxx方法根据毫秒/秒...获取Instant对象
//毫秒
Instant instant1 = Instant.ofEpochMilli(0L);
System.out.println(instant1);
//过了1秒 + 1000000000纳秒
Instant instant2 = Instant.ofEpochSecond(1L,1000000000L);
System.out.println(instant2);
Instant方法atZone()与ZoneDateTime带时区的时间类结合,输出带时区的时间
//atZone()指定时区
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Chongqing"));
System.out.println(time);
isXxx判断,minusXxx减少
//isXxx判断
Instant instant3 = Instant.ofEpochMilli(0L);
Instant instant4 = Instant.ofEpochMilli(3000L);
//用于时间的判断isBefore
System.out.println(instant3.isBefore(instant4));
System.out.println(instant3.isAfter(instant4));
//minusXxx减少
System.out.println(instant4);
System.out.println(instant4.minusSeconds(1));
ZoneDateTime带时区的时间
通过Instant + ZonedDateTime时区的方法ofInstant(instant, zoneId)指定获取时间对象,创建的对象具有不可变性,使用方法改变数值会创建新的对象原对象值不改变
//通过Instant + ZonedDateTime时区的方法ofInstant(instant, zoneId)指定获取时间对象
Instant instant = Instant.ofEpochMilli(0L);
ZoneId zoneId = ZoneId.of("Asia/Chongqing");
ZonedDateTime time = ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(time);
//withXxx修改时间(对象不可变)
System.out.println(time.withYear(2000));
System.out.println(time);
//minusXxx,plusXxx增加减少
System.out.println(time.minusYears(1));
System.out.println(time.plusYears(1));
1.2 DateTimeFormatter
用于时间的解析、格式化。
public static void main(String[] args) throws ParseException {
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
//解析
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EE a");
//格式化
System.out.println(dtf.format(time));
}
2.日历和工具类
2.1 LocalDate,LocalTime,LocalDateTime
LocalDate,获取年月日
//获取当前时间的日历对象(年月日)
LocalDate now = LocalDate.now();
System.out.println(now);
//获取指定时间的日历对象
LocalDate ldDate = LocalDate.of(2023, 3,1);
System.out.println(ldDate);
//getXxx获取日历的属性值,获取年
int year = ldDate.getYear();
System.out.println(year);
//获取月需要注意
Month m = ldDate.getMonth();
System.out.println(m);
System.out.println(m.getValue());
int m1 = ldDate.getMonthValue();
System.out.println(m1);
//获取日
int day = ldDate.getDayOfMonth();
System.out.println(day);
//获取年的第几天
int dayofyear = ldDate.getDayOfYear();
System.out.println(dayofyear);
//获取星期需要注意
DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
System.out.println(dayOfWeek);
System.out.println(dayOfWeek.getValue());
//isXxx判断
System.out.println(ldDate.isBefore(ldDate));
System.out.println(ldDate.isAfter(ldDate));
//with修改
LocalDate withLocalDate = ldDate.withYear(1999);
System.out.println(withLocalDate);
//minus减,plus加,只能增减年月日
System.out.println(ldDate.minusYears(100));
System.out.println(ldDate.plusYears(1));
//MonthDay判断今天是否是生日
LocalDate localDate1 = LocalDate.of(2000,8,1);
LocalDate nowDate = LocalDate.now();
MonthDay birthday = MonthDay.of(localDate1.getMonth(), localDate1.getDayOfMonth());
MonthDay nowMd = MonthDay.from(nowDate);
System.out.println(birthday.equals(nowMd));
LocalTime获取时分秒,纳秒
LocalTime nowTime = LocalTime.now();
System.out.println(nowTime);
LocalDateTime获取年月日时分秒
LocalDate nowDate = LocalDate.now();
System.out.println(nowDate);
LocalTime nowTime = LocalTime.now();
System.out.println(nowTime);
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
LocalDateTime localDateTime = LocalDateTime.of(nowDate, nowTime);
System.out.println(localDateTime);
2.2工具类Duration,Period,ChrononUnit
第二个参数减第一个参数
// Duration 示例:计算时间间隔(精确到纳秒)
LocalTime endTime = LocalTime.now();
LocalTime startTime = LocalTime.ofNanoOfDay(10000000L);
Duration duration = Duration.between(startTime, endTime);
System.out.println("Duration: " + duration.toHours() + " hours " +
duration.toMinutes() + " minutes" +duration.toNanos() + " nanos");
// Period 示例:计算日期间隔(年月日)
LocalDate startDate = LocalDate.of(2023, 1, 1);
LocalDate endDate = LocalDate.of(2023, 12, 31);
Period period = Period.between(startDate, endDate);
System.out.println("Period: " + period.getMonths() + " months " +
period.getDays() + " days");
// ChronoUnit 示例:计算时间单位差值
LocalDateTime startDateTime = LocalDateTime.of(2000,1,1,1,1,1, 1000);
LocalDateTime endDateTime = LocalDateTime.now();
long daysBetween = ChronoUnit.DAYS.between(startDateTime, endDateTime);
long hoursBetween = ChronoUnit.HOURS.between(startDateTime, endDateTime);
long NanosBetween = ChronoUnit.NANOS.between(startDateTime, endDateTime);
System.out.println("Days between: " + daysBetween);
System.out.println("Hours between: " + hoursBetween);
System.out.println("Nanos between: " + NanosBetween);
包装类
1. 装箱,拆箱
JDK5提出了自动装箱和自动拆箱,这样做计算不必写拆箱装箱。
自动装箱:把基本数据类型自动变成对应的包装类。
自动拆箱:把包装类自动的变成其对象的基本数据类型。
//自动装箱
Integer num = 10;
// 编译后实际代码:
Integer num = Integer.valueOf(10);
//自动拆箱
int value = num;
// 编译后实际代码:
int value = num.intValue();
2. Integer
转化时返回String。二进制或十六进制字符串是整数的另一种表示形式,而非数值本身。例如,100
的二进制表示为"1100100"
,若返回整数类型,会丢失前导零或混淆实际数值(如二进制1100100
转为十进制数值为100
,失去转换意义)。
Java是强类型语言:每种数据在Java中都有各自的数据类型,在计算的时候,如果不是同一种数据类型,是无法直接计算的。
在类型数据转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错,8中包装类只有Character没有对应的parseXxx解析方法。
//把整数转成二进制,十六进制,注意返回的值是String
String str1 = Integer.toBinaryString(100);
System.out.println(str1);
//把整数转成八进制
System.out.println(Integer.toOctalString(100));
//把整数转成十六进制
System.out.println(Integer.toHexString(100));
//将字符串类型的整数转成int类型的整数,parseInt()解析为整数
//Java是强类型语言:每种数据在Java中都有各自的数据类型
//在计算的时候,如果不是同一种数据类型,是无法直接计算的
//在类型数据转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错
//8中包装类只有Character没有对应的parseXxx解析方法
int i = Integer.parseInt("123");
System.out.println(i);
System.out.println(i + 321);
Boolean b = Boolean.parseBoolean("true");
System.out.println(b);
手动实现parseInt()。
String s = "4567";
//校验习惯先检验错误
if (!s.matches("[1-9]\\d{0,9}")) {
System.out.println("错误");
} else {
int sum = 0;
for (int i = 0; i < s.length(); i++) {
//获取字符串字符,使用ASCII转化为数字
int c = s.charAt(i) - '0';
sum = sum * 10 + c;
}
System.out.println(sum - 123);
}
手动实现toBinaryString()。
StringBuilder sb = new StringBuilder();
int num = 4444;
System.out.println(Integer.toBinaryString(num));
while (true) {
//商得0退出
if(num == 0) {
break;
}
//获取余数
int remaindar = num % 2;
//将余数倒序插入,使用sb的insert从头部开始插入
sb.insert(0, remaindar);
num /= 2;
}
System.out.println(sb.toString());
计算活了多少天
String birthday = "2007年7月24日";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月dd日");
Date d = sdf.parse(birthday);
long time = d.getTime();
long now = System.currentTimeMillis();
long timed = now - time;
System.out.println(timed / 1000 / 60 / 60 / 24);
//JDK8
LocalDate ld1 = LocalDate.of(2007, 7, 24);
LocalDate ld2 = LocalDate.now();
long ldd = ChronoUnit.DAYS.between(ld1, ld2);
System.out.println(ldd);
JDK7,JDK8判断是闰年还是平年
//把时间设置为2000年3月1日往前减少1天看是29日还是28日
Calendar c = Calendar.getInstance();
//2才是3月
c.set(2000, 2, 1);
c.add(Calendar.DAY_OF_MONTH,-1);
System.out.println(c.get(Calendar.DAY_OF_MONTH));
//或者是设置为1月1日,再往前减少1天,输出DayofYear看是不是366天
//JDK7
LocalDate ld = LocalDate.of(2000, 3, 1);
LocalDate ld1 = ld.minusDays(1);
System.out.println(ld1.getDayOfMonth());
//JDK8,isLeapYear
System.out.println(ld.isLeapYear());
Lambda表达式
函数式编程(functional programming)是一种思想特点。面向对象是先找对象,让对象做事。函数式编程思想,忽略面向对象的复杂语法,强调做什么,而不是谁去做。Lambda表达式就是函数式编程的体现。
Lambda表达式是JDK 8开始后的一种新语法形式。
Lambda表达式可以用来简化匿名内部类的书写。Lambda表达式只能简化函数式接口的匿名内部类的写法,函数式接口:有且仅有一个抽象方法的接口叫做函数式接口,接口上方可以加@FunctionalInterface注解。Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码风格,使java语言表达能力得到提升。核心:可推到,可省略。
public class Test1 implements Swim {
public static void main(String[] args) {
Swim swimmer = new Test1();
methond(new Swim() {
@Override
public void swimming() {
System.out.println("hhhhhh");
}
});
}
public static void methond(Swim s) {
s.swimming();
}
@Override
public void swimming() {
}
}
@FunctionalInterface
interface Swim {
public abstract void swimming();
}
省略后如下
methond(()-> {
System.out.println("hhhhhh");
}
);
省略规则:
参数类型可以省略不写,如果只有一个参数,参数类型可以省略()也可以省略。如果Lambda表达式的方法体只有一行,大括号,分号,return可以省略不写,需要同时省略。
Integer[] arr = {2, 31, 13, 5, 9, 11};
Arrays.sort(arr, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return 0;
}
});
//Lambda完整格式
Arrays.sort(arr,(Integer o1, Integer o2) -> {
return 0;
}
);
//Lambda省略写法
Arrays.sort(arr, (o1, o2)-> 0);
//Lambda省略写法排序
Arrays.sort(arr, (o1, o2)-> o1 - o2);
System.out.println(Arrays.toString(arr));
利用Arrays.sort做字符串排序,使用Lambda表达式做省略。
String[] s = {"a", "aaaa", "aaa", "aa"};
// Arrays.sort(s, new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length() - o2.length();
// }
// });
//省略写法
Arrays.sort(s, (o1, o2) -> o1.length() - o2.length());
System.out.println(Arrays.toString(s));
集合
单列集合Collection,双列集合Map。
Collection是单列集合的祖宗,它的功能是全部单列集合都可以继承使用的,划分为List,Set两个系列,这三个是接口,实现两个系列的集合是实现类。
List系列:添加的元素是有序(存,取),可重复,有索引。
Set系列:添加的元素是无序,不重复,无索引。