Random
Random类
Random类位于java.util包下,Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。
相同种子数的Random对象,相同次数生成的随机数字是完全相同的。也就是说,两个种子数相同的Random对象,第一次生成的随机数字完全相同,第二次生成的随机数字也完全相同。这点在生成多个随机数字时需要特别注意。
Random对象的生成
Random类包含两个构造方法,下面依次进行介绍:
public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
public Random(long seed)
该构造方法可以通过制定一个种子数进行创建。
示例代码:
Random r = new Random(); Random r1 = new Random(10);
再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。
验证:相同种子数的Random对象,相同次数生成的随机数字是完全相同的。
package educoder;
import java.util.Random;
public class RandomTest {
public void random() {
int i = 0;
int j = 0;
Random random = new Random(1);
Random random1 = new Random(1);
i = random.nextInt();
j = random1.nextInt();
System.out.println("i:" + i + "\nj:" + j);
}
public static void main(String[] args) {
RandomTest tt = new RandomTest();
tt.random();
}
}
输出结果: 第一次: i:-1155869325 j:-1155869325
修改一下起源数字,让其等于100。
Random random = new Random(100);
Random random1 = new Random(100);
输出结果: i:-1193959466 j:-1193959466
Random类中的常用方法
Random类中的方法比较简单,每个方法的功能也很容易理解。需要说明的是,Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率是均等的。下面对这些方法做一下基本的介绍:
package educoder;
import java.util.Random;
public class RandomTest {
public static void main(String[] args) {
Random random = new Random();
System.out.println("nextInt():" + random.nextInt()); // 随机生成一个整数,这个整数的范围就是int类型的范围-2^31~2^31-1
System.out.println("nextLong():" + random.nextLong()); // 随机生成long类型范围的整数
System.out.println("nextFloat():" + random.nextFloat()); // 随机生成[0, 1.0)区间的小数
System.out.println("nextDouble():" + random.nextDouble()); // 随机生成[0, 1.0)区间的小数
System.out.println("nextBoolean():"+random.nextBoolean());//随机生成一个boolean值,生成true和false的值几率相等,也就是都是50%的几率
System.out.println("nextGaussian():"+random.nextGaussian());//随机生成呈高斯(“正态”)分布的 double 值,其平均值是 0.0,标准差是 1.0
byte[] byteArr = new byte[5];
random.nextBytes(byteArr); // 随机生成byte,并存放在定义的数组中,生成的个数等于定义的数组的个数
System.out.print("nextBytes():");
for (int i = 0; i < byteArr.length; i++) {
System.out.print(byteArr[i]+"\t");
}
System.out.println();
/**
* random.nextInt(n)
* 随机生成一个正整数,整数范围[0,n),包含0而不包含n
* 如果想生成其他范围的数据,可以在此基础上进行加减
*
* 例如:
* 1. 想生成范围在[0,n]的整数
* random.nextInt(n+1)
* 2. 想生成范围在[m,n]的整数, n > m
* random.nextInt(n-m+1) + m
* random.nextInt() % (n-m) + m
* 3. 想生成范围在(m,n)的整数
* random.nextInt(n-m+1) + m -1
* random.nextInt() % (n-m) + m - 1
* ......主要是依靠简单的加减法
*/
System.out.println("nextInt(10):" + random.nextInt(10)); // 随机生成一个整数,整数范围[0,10)
for (int i = 0; i < 5; i++) {
System.out.println("我生成了一个[3,15)区间的数,它是:" + (random.nextInt(12) + 3));
}
/**
* random.nextDouble()
* 例如:
* 1.生成[0,1.0)区间的小数
* double d1 = random.nextDouble();//直接使用nextDouble方法获得。
* 2.生成[0,5.0)区间的小数
* double d2 = random.nextDouble() * 5;//因为扩大5倍即是要求的区间。同理,生成[0,d)区间的随机小数,d为任意正的小数,则只需要将nextDouble方法的返回值乘以d即可。
* 3.生成[1,2.5)区间的小数
* double d3 = r.nextDouble() * 1.5 + 1;//生成[1,2.5)区间的随机小数,则只需要首先生成[0,1.5)区间的随机数字,然后将生成的随机数区间加1即可。
* ......同理,生成任意非从0开始的小数区间[d1,d2)范围的随机数字(其中d1不等于0),则只需要首先生成[0,d2-d1)区间的随机数字,然后将生成的随机数字区间加上d1即可。
*
*/
}
}
/*_______________________________________________________*/
输出结果:
nextInt():1842341002
nextLong():4006643082448092921
nextFloat():0.88948154
nextDouble():0.5635189241159165
nextBoolean():false
nextGaussian():1.3191426544832998
nextBytes():36 100 94 14 -98
nextInt(10):1
我生成了一个[3,15)区间的数,它是:5
我生成了一个[3,15)区间的数,它是:10
我生成了一个[3,15)区间的数,它是:10
我生成了一个[3,15)区间的数,它是:11
我生成了一个[3,15)区间的数,它是:6
JDK1.8新增方法:
package educoder;
import java.util.Random;
public class RandomTest2 {
/**
* 测试Random类中 JDK1.8提供的新方法 JDK1.8新增了Stream的概念 在Random中,为double, int,
* long类型分别增加了对应的生成随机数的方法 鉴于每种数据类型方法原理是一样的,所以,这里以int类型举例说明用法
*/
public static void main(String[] args) {
Random random = new Random();
random.ints(); // 生成无限个int类型范围内的数据,因为是无限个,这里就不打印了,会卡死的......
random.ints(10, 100); // 生成无限个[10,100)范围内的数据
/**
* 这里的toArray 是Stream里提供的方法
*/
int[] arr = random.ints(5).toArray(); // 生成5个int范围类的整数。
System.out.println(arr.length);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 生成5个在[10,100)范围内的整数
arr = random.ints(5, 10, 100).toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
/**
* 对于 random.ints(); random.ints(ori, des);
* 两个生成无限个随机数的方法,我们可以利用Stream里的terminal操作,来截断无限这个操作
*/
// limit表示限制只要5个,等价于random.ints(5)
arr = random.ints().limit(5).toArray();
System.out.println(arr.length);
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 等价于random.ints(5, 10, 100)
arr = random.ints(10, 100).limit(5).toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
/*__________________________________________________*/
输出结果:
5
1801462452
-1812435985
-1073912930
1160255210
-1342018704
80
54
16
67
82
5
-1161610558
283052091
797550518
-275356995
-1661722790
11
27
27
52
54
案例
请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:
- 设计一个密码的自动生成器:密码由大写字母/小写字母/数字组成,生成六位随机密码。
- 分别以
1、2、3作为种子数创建Random对象,生成六位随机密码进行测试。
package case4;
//密码的自动生成器:密码由大写字母/小写字母/数字组成,生成六位随机密码
import java.util.Random;
import java.util.Scanner;
public class RandomTest {
public static void main(String[] args) {
// 定义一个字符型数组
char[] pardStore = new char[62];
// 把所有的大写字母放进去 把所有的小写字母放进去 把0到9放进去
/********* Begin *********/
int j=0;
for (int i = 'A'; i <='Z' ; i++) {
pardStore[j++]=(char)i;
}
for (int m = 'a'; m <='z' ; m++) {
pardStore[j++]=(char)m;
}
for (int g = '0'; g <='9' ; g++) {
pardStore[j++]=(char)g;
}
//System.out.println(pardStore[26]);
/********* End *********/
// 分别以1、2、3作为种子数 生成6位随机密码
Scanner sc = new Scanner(System.in);
int seed = sc.nextInt();
/********* Begin *********/
char[] ans = new char[6];
//int[] aa=new int[6];
Random ran=new Random(seed);
int[]aa = ran.ints(6,0,62).toArray();
for(int k=0;k<6;k++){
//System.out.println(an);
ans[k]=pardStore[aa[k]];
}
System.out.println(ans);
/********* End *********/
}
}
Date类
Date类封装了当前日期和时间。位于java.util包。
(1)类构造方法
public Date() //使用当前日期和时间初始化对象
public Date(long date) //参数date为自从1970年1月1日子时经历的毫秒数
(2)常用方法
long getTime() | 返回从1970年1月1日午夜开始已经流逝毫秒数 |
void setTime(long time) | 将日期和时间设置为time所指定的值,time是是自从1970年1月1日午夜开始已经流逝的毫秒数 |
String toString() | 将调用Date对象转换成字符串并返回结果 |
(3)Date类示例
package com.bw;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
Date d = new Date();
System.out.println(d);
//System.out.println(d.toLocaleString());
long time1 = d.getTime();//1970-1-1 00:00:00 GMT 到现在的 总毫秒数
System.out.println(time1);
long time2 = System.currentTimeMillis();
System.out.println(time2);//1970-1-1 00:00:00 GMT 到现在的 总毫秒数
Date d2 = new Date(time2);
System.out.println(d2);
}
}
11.7.2 Calendar与GregorianCalendar类
Calendar是抽象类,提供了一套方法将毫秒数形式的时间转换成大量有用的组分,例如年、月、日、小时、分和秒。
GregorianCalendar是Calendar的具体实现,它实现了您熟悉的常规的格林尼治日历。Calendar类的getInstance()方法通常会返回一个使用默认地区和时区下的当前时间初始化的GregorianCalendar对象。
示例:CalendarDemo
11.7.3 SimpleDateFormat类
SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1.字符串转日期 2008-07-10 19:20:00 要把它转成日期,可以用
sf.format(date )
2. 日期转字符串假如把今天的日期转成字符串可用 String str = sdf.format(new Date());
3. 这个字符串内容的格式类似2008-07-10 19:20:00。
Jdk1.8日期类(LocalDate、LocalTime、LocalDateTime)
LocalDate
常用API
now() 获取默认时区的当前日期对象
now(Clock clock) 从指定时钟获取当前日期对象
now(ZoneId zone) 获取指定时区的当前日期对象
of 根据指定年月日创建LocalDate对象
getYear 获得年份
getMonthValue 获得月份(1-12)
getMonth 获得月份枚举值
getDayOfMonth 获得月份中的第几天(1-31)
getDayOfWeek 获得星期几
getDayOfYear 获得年份中的第几天(1-366)
lengthOfYear 获得当年总天数
lengthOfMonth 获得当月总天数
toEpochDay 与时间纪元(1970年1月1日)相差的天数
plusDays 加天
plusWeeks 加周
plusMonths 加月
plusYears 加年
minusDays 减年
minusWeeks 减周
minusMonths 减月
minusYears 减年
withYear 替换年份
withMonth 替换月份
withDayOfMonth 替换月份中的第几天(1-31)
withDayOfYear 替换年份中的第几天(1-366)
isBefore 是否日期在之前
isAfter 是否日期在之后
isEqual 是否是当前日期
isleapYear 是否是闰年
示例代码
public static void main(String[]args){
LocalDate now1 = LocalDate.now(); // 当前日期
LocalDate now2 = LocalDate.now(ZoneId.of("Asia/Shanghai")); // 当前日期 (指定时区)
LocalDate now3 = LocalDate.now(Clock.systemDefaultZone()); // 当前日期 (指定时钟)
LocalDate localDate = LocalDate.of(2023, 1, 1); // 指定日期 2023-01-01
//获取日期
LocalDate now = LocalDate.now();
int year = now.getYear(); // 获取年份
int month = now.getMonthValue(); // 获取月份(1-12)
Month monthEnum = now.getMonth(); // 获取月份的枚举值
int dayOfMonth = now.getDayOfMonth(); // 获取月份中的第几天(1-31)
int dayOfYear = now.getDayOfYear(); // 获取一年中的第几天(1-366)
DayOfWeek dayOfWeek = now.getDayOfWeek(); // 获取现在是星期几
int dayOfYear = now.getDayOfYear(); // 获取一年中的第几天(1-366)
int lengthOfYear = now.lengthOfYear(); // 获得当年总天数
int lengthOfMonth = now.lengthOfMonth(); // 获得当月总天数
long epochDay = now.toEpochDay(); // 与时间纪元(1970年1月1日)相差的天数
//修改日期
LocalDate now = LocalDate.now();
LocalDate localDate1 = now.plusDays(1); // 给当前时间加一天
LocalDate localDate2 = now.plusDays(1); // 给当前时间加一周
LocalDate localDate3 = now.plusMonths(1); // 给当前时间加一月
LocalDate localDate4 = now.plusYears(1); // 给当前时间加一年
LocalDate localDate5 = now.minusDays(1); // 给当前时间减一天
LocalDate localDate6 = now.minusWeeks(1); // 给当前时间减一周
LocalDate localDate7 = now.minusMonths(1); // 给当前时间减一月
LocalDate localDate8 = now.minusYears(1); // 给当前时间减一年
LocalDate now = LocalDate.now();
LocalDate localDate1 = now.withYear(2020); // 修改日期对象年份为2020
LocalDate localDate2 = now.withMonth(1); // 修改日期对象月份为1
LocalDate localDate3 = now.withDayOfMonth(1); // 修改日期对象的日期(一月中的第几天)
LocalDate localDate4 = now.withDayOfYear(1); // 修改日期对象的日期(一年中的第几天)
//日期比较
LocalDate now = LocalDate.now();
LocalDate localDate = LocalDate.of(2023, 1, 1)
boolean isBefore = localDate.isBefore(now); // localDate是否在当天之前
boolean isAfter = localDate.isAfter(now); // localDate是否在当天之后
boolean isEqual = localDate.isEqual(now); // localDate是否在当天
boolean isLeapYear = localDate.isLeapYear(); // localDate是否是闰年
}
LocalTime
常用API
now() 获取默认时区的当前时间
now(ZoneId zone) 获取指定时区的当前时间
now(Clock clock) 从指定时钟获取当前时间
of 根据指定的时、分、秒获取LocalTime 实例
getHour 获取小时
getMinute 获取分钟
getSecond 获取秒
getNano 获取纳秒
plusHours 增加小时数
plusMinutes 增加分钟数
plusSeconds 增加秒数
plusNanos 增加纳秒数
minusHours 减少小时数
minusMinutes 减少分钟数
minusSeconds 减少秒数
minusNanos 减少纳秒数
withHour 替换小时
withMinute 替换分钟
withSecond 替换秒钟
withNano 替换纳秒
compareTo 时间与另一个时间比较
isAfter 检查时间是否在指定时间之后
isBefore 检查时间是否在指定时间之前
示例代码
public static void main(String[]args){
//获取时间
LocalTime now1 = LocalTime.now(); // 当前时间
LocalTime now2 = LocalTime.now(ZoneId.of("Asia/Shanghai")); // 当前时间 (指定时区)
LocalTime now3 = LocalTime.now(Clock.systemDefaultZone()); // 当前时间 (指定时钟)
LocalTime localTime = LocalTime.of(9, 9, 9); // 指定时间 09:09:09
LocalTime now = LocalTime.now();
int hour = now.getHour(); // 获取小时
int minute = now.getMinute(); // 获取小时
int second = now.getSecond(); // 获取秒
int nano = now.getNano(); // 获取纳秒
//修改日期
LocalTime now = LocalTime.now();
LocalTime localTime1 = now.plusHours(1); // 给当前时间加一小时
LocalTime localTime2 = now.plusMinutes(1); // 给当前时间加一分钟
LocalTime localTime3 = now.plusSeconds(1); // 给当前时间加一秒
LocalTime localTime4 = now.plusNanos(1); // 给当前时间加一纳秒
LocalTime localTime1 = now.minusHours(1); // 给当前时间减一小时
LocalTime localTime2 = now.minusMinutes(1); // 给当前时间减一分钟
LocalTime localTime3 = now.minusSeconds(1); // 给当前时间减一秒
LocalTime localTime4 = now.minusNanos(1); // 给当前时间减一纳秒
LocalTime now = LocalTime.now();
LocalDate localTime1 = now.withHour(1); // 修改时间对象小时为1
LocalDate localTime2 = now.withMinute(1); // 修改时间对象分钟为1
LocalDate localTime3 = now.withSecond(1); // 修改时间对象秒钟为1
LocalDate localTime4 = now.withNano(1); // 修改时间对象纳秒为1
//日期比较
LocalTime now = LocalTime.now();
LocalTime localTime = LocalTime.of(9, 9, 9);
int compare = localTime.compareTo(now); // localTime和当前时间比较--0(相等)正数(大)负数(小)
boolean after = localTime.isAfter(now); // localTime是否在当前时间之后
boolean before = localTime.isBefore(now); // localTime是否在当前时间之前
}
LocalDateTime
常用API
now() 获取默认时区的当前日期时间
now(Clock clock) 从指定时钟获取当前日期时间
now(ZoneId zone) 获取指定时区的当前日期时间
of(LocalDate date, LocalTime time) 根据日期和时间对象获取LocalDateTime 对象
of(int year, Month month, int dayOfMonth, int hour, int minute, int second) 根据指定的年、月、日、时、分、秒获取LocalDateTime 实例
getYear 获取年份
getMonth 使用月份枚举类获取月份
getDayOfMonth 获取日期在该月是第几天
getDayOfWeek 获取日期是星期几
getDayOfYear 获取日期在该年是第几天
getHour 获取小时
getMinute 获取分钟
getSecond 获取秒
getNano 获取纳秒
plusYears 增加年
plusMonths 增加月
plusWeeks 增加周
plusDays 增加天
plusHours 增加小时
plusMinutes 增加分
plusSeconds 增加秒
plusNanos 增加纳秒
minusYears 减少年
minusMonths 减少月
meminusWeeks 减少周
minusDays 减少天
minusHours 减少小时
minusMinutes 减少分
minusSeconds 减少秒
minusNanos 减少纳秒
withYear 替换年份
withMonth 替换月份
withDayOfMonth 替换月份中的第几天(1-31)
withDayOfYear 替换年份中的第几天(1-366)
withHour 替换小时
withMinute 替换分钟
withSecond 替换秒钟
withNano 替换纳秒
isEqual 判断日期时间是否相等
isBefore 检查是否在指定日期时间之前
isAfter 检查是否在指定日期时间之后
示例代码
public static void main(String[]args){
//获取日期
// 当前日期
LocalDateTime now1 = LocalDateTime.now();
//当前日期 (指定时区)
LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
//当前日期 (指定时钟)
LocalDateTime now3 = LocalDateTime.now(Clock.systemDefaultZone());
//指定日期 2023-01-01 01:01:00
LocalDateTime localDateTime1 = LocalDateTime.of(2023, 1, 1, 1, 1);
//使用LocalDate和LocalTime对象创建LocalDateTime对象
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
LocalDateTime now = LocalDateTime.now();
int year = now.getYear(); // 获取年份
Month month = now.getMonth(); // 使用月份枚举值
int dayOfMonth = now.getDayOfMonth(); // 获取日期在该月是第几天
DayOfWeek dayOfWeek = now.getDayOfWeek(); // 获取日期是星期几
int dayOfYear = now.getDayOfYear(); // 获取日期在该年是第几天
int hour = now.getHour(); // 获取小时
int minute = now.getMinute(); // 获取分钟
int second = now.getSecond(); // 获取秒钟
int nano = now.getNano(); // 获取纳秒
//修改日期
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime1 = now.plusDays(1); // 给当前时间加一天
LocalDateTime localDateTime2 = now.plusDays(1); // 给当前时间加一周
LocalDateTime localDateTime3 = now.plusMonths(1); // 给当前时间加一月
LocalDateTime localDateTime4 = now.plusYears(1); // 给当前时间加一年
LocalDateTime localDateTime5 = now.plusHours(1); // 给当前时间加一小时
LocalDateTime localDateTime6 = now.plusMinutes(1); // 给当前时间加一分钟
LocalDateTime localDateTime7 = now.plusSeconds(1); // 给当前时间加一秒
LocalDateTime localDateTime8 = now.plusNanos(1); // 给当前时间加一纳秒
LocalDateTime localDateTime9 = now.minusDays(1); // 给当前时间减一天
LocalDateTime localDateTime10 = now.minusWeeks(1); // 给当前时间减一周
LocalDateTime localDateTime11 = now.minusMonths(1); // 给当前时间减一月
LocalDateTime localDateTime12 = now.minusYears(1); // 给当前时间减一年
LocalDateTime localDateTime13 = now.minusHours(1); // 给当前时间减一小时
LocalDateTime localDateTime14 = now.minusMinutes(1); // 给当前时间减一分钟
LocalDateTime localDateTime15 = now.minusSeconds(1); // 给当前时间减一秒
LocalDateTime localDateTime16 = now.minusNanos(1); // 给当前时间减一纳秒
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDate1 = now.withYear(2020); // 修改日期对象年份为2020
LocalDateTime localDate2 = now.withMonth(1); // 修改日期对象月份为1
LocalDateTime localDate3 = now.withDayOfMonth(1); // 修改日期对象的日期(一月中的第几天)
LocalDateTime localDate4 = now.withDayOfYear(1); // 修改日期对象的日期(一年中的第几天)
LocalDateTime localTime1 = now.withHour(1); // 修改时间对象小时为1
LocalDateTime localTime2 = now.withMinute(1); // 修改时间对象分钟为1
LocalDateTime localTime3 = now.withSecond(1); // 修改时间对象秒钟为1
LocalDateTime localTime4 = now.withNano(1); // 修改时间对象纳秒为1
//日期比较
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(2023, 1, 1, 1, 1);
boolean isBefore = localDateTime.isBefore(now); // localDateTime是否在当天之前
boolean isAfter = localDateTime.isAfter(now); // localDateTime是否在当天之后
boolean isEqual = localDateTime.isEqual(now); // localDateTime是否在当天
}