一、和数学相关的API
1、java.lang.Math类,它是数学计算的工具类。
包含用于执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。
Math类所有可用的方法都是static修饰的,也就是说我们需要通过“Math.方法”去使用它们。
(1)double Math.random():产生[0,1)的随机数
(2)double Math.sqrt(double x):求x的平方根
(3)double pow(double x, double b):求a的b次方
(4)double ceil(double a):向上取整,结果是double类型
(5)double floor(double a):向下取整,结果是double类型
(6)long round(double a):四舍五入,结果是long类型
(7)int max(int a, int b) :求a和b的最大值,有多种重载形式,即支持多种数据类型
(8)int min(int a, int b) :求a和b的最小值,有多种重载形式,即支持多种数据类型
(9)int abs(int a) :求绝对值,有多种重载形式,即支持多种数据类型
(10)常量:Math.PI圆周率
2、java.math包
(1)BigDecimal:任意精度的定点小数
(2)BigInteger:任意大小的整数
BigDecimal和BigInteger是引用数据类型,又不是包装类,不支持与基本数据类型之间的自动转换。
BigDecimal和BigInteger它们的数据表示,必须new对象。
BigDecimal和BigInteger是引用数据类型,就不能直接使用“运算符”进行计算,需要调用方法来完成计算功能。
当开发中,计算时,参与的数字比较大,或者要求的精度范围比较大,那么可以考虑使用BigDecimal和BigInteger,
而不用double,float,long,int等基本数据类型。
3、java.util.Random:产生随机数
Math.random()产生[0,1)范围的小数
int nextInt():int范围内的任意值
double nextDouble:产生[0,1)范围的小数
int nextInt(int n):在[0,n)范围内产生int随机数
public class TestMath {
@Test
public void test6(){
Random rand = new Random(100); //根据种子,每次运行产生的随机数是一样的
System.out.println("随机整数:" + rand.nextInt());//-1193959466
System.out.println("随机整数:" + rand.nextInt(100));//50
System.out.println("随机小数:" + rand.nextDouble());//0.19497605734770518
}
@Test
public void test5(){
Random rand = new Random();//没有指定种子,默认种子是和系统时间有关,每次运行结果是不同的
System.out.println("随机整数:" + rand.nextInt());//1708858262
System.out.println("随机整数:" + rand.nextInt(100));//29
System.out.println("随机小数:" + rand.nextDouble());//0.4636514517569357
}
@Test
public void test4(){
BigDecimal b1 = new BigDecimal("857948515111111.54554744547895111111265475");
BigDecimal b2 = new BigDecimal("9795862478.2212785851511111154554744547895111111265475851211");
System.out.println("和:" + b1.add(b2));
System.out.println("差:" + b1.subtract(b2));
System.out.println("积:" + b1.multiply(b2));
//System.out.println("除:" + b1.divide(b2));//java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
System.out.println("除:" + b1.divide(b2,50,BigDecimal.ROUND_FLOOR));
//87582.74394098036049261626793704997773704251577106577718
System.out.println("除:" + b1.divide(b2,52,BigDecimal.ROUND_CEILING));
//除:87582.7439409803604926162679370499777370425157710657771878
System.out.println("余:" + b1.remainder(b2));
}
@Test
public void test3(){
BigInteger b1 = new BigInteger("85794851511111154554744547895111111265475");
BigInteger b2 = new BigInteger("97958624782212785851511111154554744547895111111265475");
System.out.println("和:" + b1.add(b2));
System.out.println("差:" + b1.subtract(b2));
System.out.println("积:" + b1.multiply(b2));
System.out.println("除:" + b1.divide(b2)); //整数/整数,结果只保留整数部分
System.out.println("余:" + b1.remainder(b2));
System.out.println("-------------------------------");
System.out.println("和:" + b2.add(b1));
System.out.println("差:" + b2.subtract(b1));
System.out.println("积:" + b2.multiply(b1));
System.out.println("除:" + b2.divide(b1)); //整数/整数,结果只保留整数部分
System.out.println("余:" + b2.remainder(b1));
}
@Test
public void test2(){
System.out.println(Math.ceil(3.6));//4.0
System.out.println(Math.floor(3.6));//3.0
System.out.println(Math.round(3.6));//4
System.out.println("--------------------------");
System.out.println(Math.ceil(3.3));//4.0
System.out.println(Math.floor(3.3));//3.0
System.out.println(Math.round(3.3));//3
}
@Test
public void test1(){
System.out.println(Math.random());
System.out.println(Math.sqrt(9.0));
System.out.println(Math.sqrt(8)); //8自动提升为double
System.out.println(Math.pow(2,5));//32.0
System.out.println(Math.pow(2.5, 1.2));//3.002811084953578
}
}
二、日期时间API
第一代:Date类等
第二代:Calendar等
第三代:LocalDate等
1、java.util.Date类
Date类的对象 表示特定的瞬间,精确到毫秒。
(1)无参构造:new Date()
(2)无参构造:new Date(毫秒值)
(3)long getTime():返回当前日期时间对象距离1970-1-1 0:0:0 0毫秒的毫秒差值
2、java.util.Calendar类
Calendar类代表日历类型。
Calendar类是抽象类,不能直接创建对象,只能创建子类对象,例如:GregorianCalendar (格里高利日历)子类。
子类GregorianCalendar (格里高利日历)不好记,Calendar提供了一些静态方法:
static Calendar getInstance():使用默认时区和语言环境获得一个日历。
static Calendar getInstance(TimeZone zone, Locale aLocale):使用指定时区和语言环境获得一个日历。
3、Locale:语言环境 和 TimeZone:时区
Java中一切皆对象,把语言环境和时区也用对象表示。
4、java.text.DateFormat:日期时间格式化
DateFormat是抽象类,不能直接new对象,要么通过new直接创建子类对象来使用 或调用 静态方法static DateFormat getDateInstance() 获取子类对象。
直接子类:SimpleDateFormat
DateFormat和SimpleDateFormat只为Date类型提供了支持,没有直接对Calendar类提供支持。
(1)把日期时间对象转为字符串:format方法
(2)把字符串转为日期时间对象:parse方法
SimpleDateFormat类中定义了以下模式字母(所有其他字符 'A' 到 'Z' 和 'a' 到 'z' 都被保留):
字母 日期或时间元素 表示 示例
G Era 标志符 Text AD
y 年 Year 1996; 96
M 年中的月份 Month July; Jul; 07
w 年中的周数 Number 27
W 月份中的周数 Number 2
D 年中的天数 Number 189
d 月份中的天数 Number 10
F 月份中的星期 Number 2
E 星期中的天数 Text Tuesday; Tue
a Am/pm 标记 Text PM
H 一天中的小时数(0-23) Number 0
k 一天中的小时数(1-24) Number 24
K am/pm 中的小时数(0-11) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
S 毫秒数 Number 978
z 时区 General time zone Pacific Standard Time; PST; GMT-08:00
Z 时区 RFC 822 time zone -0800
5、JDK1.8引入了第三代日期时间API
因为原来的第一代和第二代用起来很麻烦,而且有一些问题:
(1)日期时间对象可变。正常逻辑中,某个日期时间对象,就应该代表某个固定的日期时间值。
例如:c1对象 对应 2021-8-18日期
2009-1-18应该用另个一Calendar对象表示。
(2)偏移性:Date中的年份是从1900开始的,而月份都是从0开始的。
(3)格式化只对Date有用,Calendar则不行。
(4)此外,它们也不是线程安全的,不能处理闰秒等。
JDK1.8在如下包中,增加了第三代的日期时间API:
* java.time – 包含值对象的基础包
* java.time.chrono – 提供对不同的日历系统的访问。
* java.time.format – 格式化和解析时间和日期
* java.time.temporal – 包括底层框架和扩展特性
* java.time.zone – 包含时区支持的类
6、第三代日期时间API中常用的类型
(1)本地日期时间:LocalDate、LocalTime、LocalDateTime
A:now()获取系统日期或时间
B:of()
C:plusXxx
D:minusXxx
E:isLeapYear():判断是否闰年
F:getXXX
注意:1.8的第三代的日期时间对象是不可变的,修改以后,需要用变量重新接收,否则原来变量仍然表示原来的对象。
(2)指定时区日期时间:ZondId和ZonedDateTime
(3)持续日期/时间:Period和Duration
Period:日期间隔
Duration:时间间隔
(4)DateTimeFormatter:日期时间格式化
A:DateTimeFormatter.常量字段
例如:DateTimeFormatter.ISO_DATE_TIME
B: FormatStyle枚举类型指定的常量对象:LONG,MEDIUM,SHORT
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
C:配合y,M,D,d等模式来使用
DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss SSS毫秒 这是这一年的第D天,这一天是E");
public class TestDate {
@Test
public void test21() {
LocalDateTime now = LocalDateTime.now();
// DateTimeFormatter df1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);//FULL对于时间来说,必须有时区信息在里面
// System.out.println(df1.format(now));//异常
DateTimeFormatter df1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.of("Asia/Shanghai"));
System.out.println(df1.format(now));//2021年8月18日 星期三 下午02时36分56秒 CT
}
@Test
public void test20() {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);//2021-08-18T14:09:56.679
DateTimeFormatter d1 = DateTimeFormatter.ISO_DATE_TIME;
DateTimeFormatter d2 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
System.out.println(d1.format(now));//2021-08-18T14:10:34.587
System.out.println(d2.format(now));//2021-08-18T14:10:34.587
ZonedDateTime time = ZonedDateTime.now(ZoneId.of("America/Toronto"));
System.out.println(d1.format(time));//2021-08-18T02:29:48.845-04:00[America/Toronto]
System.out.println(d2.format(time));//2021-08-18T02:29:48.845
}
@Test
public void test19() {
LocalDateTime now = LocalDateTime.now();
System.out.println(now);//2021-08-18T14:09:56.679
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME;
System.out.println(dateTimeFormatter.format(now));//2021-08-18T14:10:34.587
DateTimeFormatter df1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
System.out.println(df1.format(now));//2021年8月18日 下午02时11分52秒
DateTimeFormatter df2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println(df2.format(now));//2021-8-18 14:12:34
DateTimeFormatter df3 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
System.out.println(df3.format(now));//21-8-18 下午2:12
DateTimeFormatter smiple = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss SSS毫秒 这是这一年的第D天,这一天是E");
System.out.println(smiple.format(now));//2021年08月18日 14:14:56 409毫秒 这是这一年的第230天,这一天是星期三
}
@Test
public void test18() {
LocalTime now = LocalTime.now();
LocalTime ye = LocalTime.of(23,59,59);
Duration d = Duration.between(now,ye);
System.out.println(d);//PT9H51M3.908S
}
@Test
public void test17() {
LocalDate today = LocalDate.now();
LocalDate dan = LocalDate.of(2022, 1, 1);
Period p = Period.between(today,dan );
System.out.println(p);//P4M14D
System.out.println(p.getDays());//14
System.out.println(p.getMonths());//4
System.out.println(p.getYears());//0
}
@Test
public void test16() {
ZonedDateTime localTime = ZonedDateTime.now();
System.out.println(localTime);//2021-08-18T14:02:02.005+08:00[Asia/Shanghai]
ZonedDateTime time = ZonedDateTime.now(ZoneId.of("America/Toronto"));
System.out.println(time);//2021-08-18T02:03:31.194-04:00[America/Toronto]
}
@Test
public void test15() {
LocalDate date = LocalDate.of(2020, 7, 28);
System.out.println(date.getYear());//2020
System.out.println(date.getMonth());//JULY
System.out.println(date.getMonthValue());//7
System.out.println(date.getDayOfMonth());//28
}
@Test
public void test14() {
LocalDate date = LocalDate.of(2020, 7, 28);
System.out.println(date.isLeapYear());//true
}
@Test
public void test13() {
LocalDate kai = LocalDate.of(2021, 7, 28);
System.out.println(kai);
LocalDate future = kai.plusDays(200);
System.out.println(future);//2022-02-13
}
@Test
public void test12() {
LocalDate kai = LocalDate.of(2021, 7, 28);
System.out.println(kai);//2021-07-28
LocalTime time = LocalTime.of(9,0,0);
System.out.println(time);//09:00
LocalDateTime t = LocalDateTime.of(2021, 7, 28,9,0,0);
System.out.println(t);//2021-07-28T09:00
}
@Test
public void test11() {
LocalDate today = LocalDate.now();
System.out.println(today);//2021-08-18
LocalTime now = LocalTime.now();
System.out.println(now);//11:56:38.947
LocalDateTime t = LocalDateTime.now();
System.out.println(t);//2021-08-18T11:57:10.718
}
@Test
public void test10() {
Calendar c1 = Calendar.getInstance();
System.out.println("年份:" + c1.get(Calendar.YEAR));//2021
System.out.println("月份:" + (c1.get(Calendar.MONTH) +1 ));//8
System.out.println("日:" + c1.get(Calendar.DATE ));//18
//2021-8-18
c1.set(Calendar.YEAR, 2008);
c1.set(Calendar.MONTH, 12); //月份正常值是[0,11]
System.out.println("年份:" + c1.get(Calendar.YEAR));//2009
System.out.println("月份:" + (c1.get(Calendar.MONTH) +1 ));//1
System.out.println("日:" + c1.get(Calendar.DATE ));//18
//2009-1-18
}
@Test
public void test09() {
Scanner input = new Scanner(System.in);
System.out.print("请输入生日(格式:1990-8-6):");
String birth = input.next();
try {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sf.parse(birth );
SimpleDateFormat sf2 = new SimpleDateFormat("出生当天是这一年的第D天");
System.out.println(sf2.format(date));//出生当天是这一年的第218天
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test08() {
Date d = new Date();
SimpleDateFormat sf = new SimpleDateFormat();
System.out.println(sf.format(d));//21-8-18 上午11:37
SimpleDateFormat sf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss SSS毫秒 这是这一年的第D天,这一天是E");
System.out.println(sf2.format(d));//2021年08月18日 11:40:25 485毫秒 这是这一年的第230天,这一天是星期三
}
@Test
public void test07() {
Calendar c1 = Calendar.getInstance(TimeZone.getTimeZone("America/Toronto"),Locale.CANADA); //加拿大多伦多
System.out.println(c1);
System.out.println("年份:" + c1.get(Calendar.YEAR));//2021
System.out.println("月份:" + (c1.get(Calendar.MONTH) +1 ));//8
System.out.println("日:" + c1.get(Calendar.DATE ));//17
System.out.println("时:" + c1.get(Calendar.HOUR));//11 12小时制
System.out.println("时:" + c1.get(Calendar.HOUR_OF_DAY));//23 24小时制度
System.out.println("分:" + c1.get(Calendar.MINUTE));//32
System.out.println("秒:" + c1.get(Calendar.SECOND));//18
}
@Test
public void test06() {
Locale china1 = Locale.CHINA;
Locale china2 = new Locale("zh","CN");
TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
String[] availableIDs = TimeZone.getAvailableIDs();//获取所有时区的ID
for (int i = 0; i < availableIDs.length; i++) {
System.out.println(availableIDs[i]);
}
}
@Test
public void test05(){
Calendar c1 = Calendar.getInstance();
System.out.println(c1);
/*
...
YEAR=2021,
MONTH=7, 月份从0开始
WEEK_OF_YEAR=34,
WEEK_OF_MONTH=3,
DAY_OF_MONTH=18,
DAY_OF_YEAR=230,
DAY_OF_WEEK=4, 周日是一个星期的第1天
DAY_OF_WEEK_IN_MONTH=3,
AM_PM=0,
HOUR=11,
HOUR_OF_DAY=11,
MINUTE=22,
SECOND=27,
MILLISECOND=262
*/
System.out.println("年份:" + c1.get(Calendar.YEAR));//2021
System.out.println("月份:" + (c1.get(Calendar.MONTH) +1 ));//8
}
@Test
public void test04(){
// Calendar c1 = new Calendar() ;//错误,因为Calendar是抽象类
Calendar c1 = new GregorianCalendar();
}
@Test
public void test03(){
long time = Long.MAX_VALUE;
Date d2 = new Date(time);
System.out.println(d2);//Sun Aug 17 15:12:55 CST 292278994
}
@Test
public void test02(){
long time = Integer.MAX_VALUE;
Date d2 = new Date(time);
System.out.println(d2);//Mon Jan 26 04:31:23 CST 1970
}
@Test
public void test01(){
Date d1 = new Date();
System.out.println(d1);
//Wed Aug 18 11:12:57 CST 2021
//Date类的toString方法,没有显示毫秒值
long time = d1.getTime();//返回当前日期时间对象,对应的毫秒值
System.out.println(time);//1629256449466 距离1970-1-1 0:0:0 0毫秒的毫秒差值
}
}
三、数组工具类
1、回忆之前学习的数组的算法
(1)在数组中找最大值
(2)在数组中找最大值及其下标
(3)在数组中查找某个元素是否存在,并返回下标
A:顺序查找
B:二分查找
(4)统计分析数组中的元素情况
A:求总和
B:找偶数的个数
C:找3的倍数的个数
...
(5)冒泡排序
ublic class TestArray {
@Test
public void test17() {
int[] arr = {2, 4, 5, 1, 6};
System.out.println(Arrays.toString(arr));//[2, 4, 5, 1, 6]
}
@Test
public void test16() {
Student[] arr = new Student[3];
arr[0] = new Student(2,"张三",78);
arr[1] = new Student(1,"李四",98);
arr[2] = new Student(3,"王五",60);
Arrays.sort(arr,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student) o1;
Student s2 = (Student) o2;
int result = s1.getScore() - s2.getScore();
return result == 0 ? s1.getId() - s2.getId() : result;
}
});//传入一个Comparator的实现类,重写compare方法
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] );
}
}
@Test
public void test15() {
Student[] arr = new Student[3];
arr[0] = new Student(2,"张三",78);
arr[1] = new Student(1,"李四",98);
arr[2] = new Student(3,"王五",60);
Arrays.sort(arr);//要求Student类实现Comparable接口,重写compareTo方法
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] );
}
}
@Test
public void test14() {
int[] arr = {2, 4, 5, 1, 6};
Arrays.sort(arr);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test13() {
int[] arr = new int[5];
Arrays.fill(arr, -1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test12() {
int[] arr1 = {1, 6, 9, 12, 67};
int[] arr2 = {1, 6, 9, 12, 67, 34};
System.out.println(Arrays.equals(arr1, arr2));
}
@Test
public void test11() {
int[] arr = {1, 6, 9, 12, 67};
int[] newArr1 = Arrays.copyOfRange(arr,2,8);
for (int i = 0; i < newArr1.length; i++) {
System.out.print(newArr1[i] + " ");
}
System.out.println();//9 12 67
}
@Test
public void test10() {
int[] arr = {1, 6, 9, 12, 67};
int[] newArr1 = Arrays.copyOf(arr, 3);
for (int i = 0; i < newArr1.length; i++) {
System.out.print(newArr1[i] + " ");
}
System.out.println();
int[] newArr2 = Arrays.copyOf(arr, 5);
for (int i = 0; i < newArr2.length; i++) {
System.out.print(newArr2[i] + " ");
}
System.out.println();
int[] newArr3 = Arrays.copyOf(arr, 10);
for (int i = 0; i < newArr3.length; i++) {
System.out.print(newArr3[i] + " ");
}
System.out.println();
}
@Test
public void test09() {
int[] arr = {1, 6, 9, 12, 67};//数组必须有序
int target = 12;
int index = Arrays.binarySearch(arr, target);
if(index < 0){
System.out.println(target +"不存在");
}else{
System.out.println(target+"在[" +index +"]位置");
}
}
@Test
public void test08() {
int[] arr = {2, 4, 5, 1, 6};
//冒泡排序
for(int i=1; i<arr.length; i++){
for(int j=0; j<arr.length-i; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//遍历结果
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
@Test
public void test07() {
int[] arr = {1, 6, 9, 12, 67};
//统计偶数的个数
int count = 0;
for (int i=0; i<arr.length; i++){
if(arr[i]%2==0){
count++;
}
}
System.out.println("count = " + count);
}
@Test
public void test06(){
int[] arr = {1,6,9,12,67};//数组必须有序
int target = 1;//查找目标
int index = -1;
//二分查找
for(int left=0,right=arr.length-1; left<=right;){
int mid = left + (right-left)/2; //mid = (left+right)/2;
if(arr[mid] == target){
index = mid;
break;
}else if(target < arr[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}
if(index == -1){
System.out.println(target +"不存在");
}else{
System.out.println(target+"在[" +index +"]位置");
}
}
@Test
public void test05(){
String[] strings = {"hello","java","world"};
//顺序查找
String target = "张三";
int index = -1;
for (int i = 0; i < strings.length; i++) {
if(strings[i].equals(target)){
index = i;
break;
}
}
if(index == -1){
System.out.println(target +"不存在");
}else{
System.out.println(target+"在[" +index +"]位置");
}
}
@Test
public void test04(){
int[] arr = {2,4,5,1,6};
//顺序查找
// int target = 3;//查找目标
int target = 1;//查找目标
int index = -1;
for (int i = 0; i < arr.length; i++) {
if(arr[i] == target){
index = i;
break;
}
}
if(index == -1){
System.out.println(target +"不存在");
}else{
System.out.println(target+"在[" +index +"]位置");
}
}
@Test
public void test03(){
int[] arr = {2,4,5,1,6};
//找最大值及其下标
int maxIndex = 0;//假设第一个最大
for(int i=1; i<arr.length; i++){
if(arr[i] > arr[maxIndex]){
maxIndex = i;
}
}
System.out.println("max = " + arr[maxIndex]);
System.out.println("最大值下标index = " + maxIndex);
}
@Test
public void test02(){
int[] arr = {2,4,5,1,6};
//找最大值及其下标
int max = arr[0];//假设第一个最大
int index = 0;
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
index = i;
}
}
System.out.println("max = " + max);
System.out.println("最大值下标index = " + index);
}
@Test
public void test01(){
int[] arr = {2,4,5,1,6};
//找最大值
int max = arr[0];//假设第一个最大
for(int i=1; i<arr.length; i++){
if(arr[i] > max){
max = arr[i];
}
}
System.out.println("max = " + max);
}
}
class Student implements Comparable {
private int id;
private String name;
private int score;
public Student(int id, String name, int score) {
this.id = id;
this.name = name;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Object o) {
return this.id - ((Student)o).id;
}
}
2、数组工具类:java.util.Arrays
它里面的方法都是静态的,可以完成数组的各种运算:
(1)public static int binarySearch(int[] a, int key) :使用二分查找法,在数组中查找目标
(2)public static int[] copyOf(int[] original,int newLength):复制一个新数组,新数组的长度为newLength
(3)public static int[] copyOfRange(int[] original, int from, int to):复制一个新数组,新数组的长度为(to-from)
左闭右开,[from ,to)
(4)public static boolean equals(int[] a, int[] a2):比较两个数组是否长度和内容一致
(5)public static void fill(int[] a,int val):用val填充整个数组
(6)public static void sort(int[] a) :排序
public static void sort(Object[] a) :自然排序
public static void sort(Object[] a, Comparator c) :定制排序
(7)public static String toString(int[] a):返回数组的元素列表,[元素1,元素2...]
3、补充
(1)数组的反转
方案一:首尾交换
方案二:借助一个新数组,倒着放元素
推荐用方案一:时空消耗低
(2)数组元素的插入
(3)数组元素的删除
(4)直接选择排序
public class TestArray2 {
@Test
public void test07(){
int[] arr = {49,38,65,97,76,13,27,49};
/*
直接选择排序
思路:每一轮找出本轮“未排序”元素的最小/大值,把它放到它应该在的位置,经过多轮后实现整体排序
例如:{49,38,65,97,76,13,27,49}
第一轮:找出本轮“未排序”元素的最小值 13, 它应该在[0]位置 交换13和arr[0]
{13,38,65,97,76,49,27,49}
第二轮: 找出本轮“未排序”元素的最小值 27,它应该在[1]位置 交换27和arr[1]
{13,27,65,97,76,49,38,49}
第三轮: 找出本轮“未排序”元素的最小值 38,它应该在[2]位置 交换38和arr[2]
{13,27,38,97,76,49,65,49}
第四轮: 找出本轮“未排序”元素的最小值 49(假设是前面49),它应该在[3]位置 交换49和arr[3]
{13,27,38,49,76,97,65,49}
第五轮: 找出本轮“未排序”元素的最小值 49(假设是后面49),它应该在[4]位置 交换49和arr[4]
{13,27,38,49,49,97,65,76}
第六轮: 找出本轮“未排序”元素的最小值 65,它应该在[5]位置 交换49和arr[5]
{13,27,38,49,49,65,97,76}
第七轮: 找出本轮“未排序”元素的最小值 76,它应该在[6]位置 交换76和arr[5]
{13,27,38,49,49,65,76,97}
n个元素,需要n-1轮
*/
for(int i=0; i<arr.length-1; i++){
//找出本轮“未排序”元素的最小值,及其位置
int min = arr[i];
int index = i;
for(int j=i+1; j<arr.length; j++){
if(arr[j] < min){
min = arr[j];
index = j;
}
}
System.out.println("本轮最小值是" + min +",它的位置是[" + index + "]");
//把最小值放到正确的位置[i]
if(index != i){
int temp = arr[index];
arr[index ] = arr[i];
arr[i] = temp;
}
System.out.println("第"+ (i+1)+"轮结果:" +Arrays.toString(arr));
}
}
@Test
public void test06() {
String[] arr = {"hello","java","atguigu","chai","mysql"};
//删除arr[2]位置的元素
//方案二:把删除位置的后面的元素前移
System.arraycopy(arr,3, arr,2,2);
System.out.println(Arrays.toString(arr));//[hello, java, chai, mysql, mysql]
//然后把最后的位置置空
arr[4] = null;
System.out.println(Arrays.toString(arr));//[hello, java, chai, mysql, null]
/*
这种方案,元素被删掉了,后期想要给这个数组增加新元素时,不需要遍历数组,直接放后面即可,对于后续操作来说更快更高薪
*/
}
@Test
public void test05() {
String[] arr = {"hello","java","atguigu","chai","mysql"};
//删除arr[2]位置的元素
//方案一:直接把arr[2] 赋值为null
arr[2] = null;
System.out.println(Arrays.toString(arr));
//这种方案,元素被删掉了,但是后期想要给这个数组增加新元素时,就需要数组,找空位
//类似于:停车场 ,车走了,新的车来了,需要绕停车场找位置,麻烦
}
@Test
public void test04() {
int[] arr = {1, 2, 3, 4, 5};
//假如,要在arr数组的[2]位置插入一个新元素6,怎么做
//(1)如果原来的数组是“满”,需要先扩容
arr = Arrays.copyOf(arr, arr.length+1); //增加一个位置
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5, 0]
//(2)把[2]位置及其后面的元素后移
System.arraycopy(arr,2,arr,3,3);
System.out.println(Arrays.toString(arr));//[1, 2, 3, 3, 4, 5]
//(3)把新元素6放到arr[2]
arr[2] = 6;
System.out.println(Arrays.toString(arr));//[1, 2, 6, 3, 4, 5]
}
@Test
public void test03() {
int[] arr = {1, 2, 3, 4, 5};
//数组反转
//思路二:借助一个新数组,把原来arr的元素倒着放到temp中
int[] temp = new int[arr.length];
for(int i=0; i<temp.length; i++){
temp[i] = arr[arr.length-1-i];
}
//让arr指向temp新数组
arr = temp;
System.out.println(Arrays.toString(arr));
}
@Test
public void test02(){
int[] arr = {1,2,3,4,5};
//数组反转
//思路:首尾交换
for(int i=0; i<arr.length; i++){//交换的次数,如果是4次,就又换回去了
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 5]
}
@Test
public void test01(){
int[] arr = {1,2,3,4,5};
//数组反转
//思路一:首尾交换
for(int i=0; i<arr.length/2; i++){//交换的次数
int temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
System.out.println(Arrays.toString(arr));
}
}
四、系统信息相关的API
1、java.lang.Runtime
Runtime:运行时环境对象,代码当前JVM的运行环境
Runtime对象是不能自己new的,通过静态方法getRuntime()获取。
Runtime的构造器是私有化的,在Runtime的内部有一个静态变量,来存储Runtime的对象,在Runtime内部创建了它的唯一的对象。
这个设计是单例(唯一的实例对象)设计。
可以获取内存信息等,例如:totalMemory()和freeMemory()
调用gc()方法通知GC工作。
2、java.lang.System类
System 类包含一些有用的类字段和方法。它不能被实例化。
(1)Java的常量字段:
out:普通信息的输出流,默认输出到控制台,如果重新set了,就不一定 打印到控制台
err:标准的错误输出流,默认输出到控制台,如果重新set了,就不一定 打印到控制台
in:默认代码键盘输入,如果重新set了,就不一定从键盘输入信息
public final static PrintStream out = null;
public final static PrintStream err = null;
public final static InputStream in = null;
为什么out,err,in的常量对象没有大写?
这些out,err,in在Java层面看起来是常量对象,因为有final修饰,
但是System类中却给他们提供了set方法进行修改。
正常情况下,final修饰成员变量是没有set方法的。
public static void setIn(InputStream in){...}
public static void setOut(PrintStream out){...}
public static void setErr(PrintStream err){...}
private static native void setIn0(InputStream in);
private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);
System类中要修改out,err,in对象是通过C底层的代码完成的,在Java层面做不了。
(2)System.exit(0).退出JVM,根据惯例,非 0 的状态码表示异常终止。
(3)gc():通知GC工作。
(4)Properties getProperties() :获取系统属性
(5)static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :复制数组
参数1:src代表的是原数组
参数2:srcPos代表的是原数组开始复制起始下标
参数3:dest代表的是目标数组
参数4:destPos代表的是目标数组开始接收复制元素的起始下标
参数5:一共复制几个元素
对于接下来学习Arrays工具类还有集合源码等来说非常重要。
public class TestRuntimeAndSystem {
@Test
public void test08(){
int[] arr = {1,2,3,4,5,6,7,8};
System.arraycopy(arr,3,arr,2,5);
/*
这个arraycopy方法非常智能,当发现是同一个数组内部从后往前复制时,会从需要复制的元素第一个开始复制
arr[3]->arr[2]
arr[4]->arr[3]
arr[5]->arr[4]
arr[6]->arr[5]
arr[7]->arr[6]
*/
//遍历arr1
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//原:1,2,3,4,5,6,7,8
//现:1 2 4 5 6 7 8 8
}
@Test
public void test07(){
int[] arr = {1,2,3,4,5,6,7,8};
System.arraycopy(arr,0,arr,1,7);
/*
这个arraycopy方法非常智能,当发现是同一个数组内部从前往后复制时,会从需要复制的元素最后一个开始复制
arr[6]->arr[7]
arr[5]->arr[6]
arr[4]->arr[5]
arr[3]->arr[4]
arr[2]->arr[3]
arr[1]->arr[2]
arr[0]->arr[1]
*/
//遍历arr1
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
//1,2,3,4,5,6,7,8
//1 1 2 3 4 5 6 7
}
@Test
public void test06(){
int[] arr = {1,2,3,4,5,6,7,8};
//arr数组内部复制
//从arr[0]开始复制,arr[0]放到arr[3],依次类推,一共复制4个元素
System.arraycopy(arr,0,arr,3,4);
/*
这个arraycopy方法非常智能,当发现是同一个数组内部从前往后复制时,会从需要复制的元素最后一个开始复制
arr[3] -> arr[6]
arr[2] -> arr[5]
arr[1] -> arr[4]
arr[0] -> arr[3]
*/
//遍历arr1
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");//1 2 3 1 2 3 4 8
}
//原:1 2 3 4 5 6 7 8
//现:1 2 3 1 2 3 4 8
}
@Test
public void test05(){
int[] arr1 = new int[10];
int[] arr2 = {1,2,3,4,5};
//把arr2数组的元素复制到arr1中,把arr2从[0]位置开始复制,放到arr1中从[3]位置开始放,一共复制3个元素
System.arraycopy(arr2,0,arr1,3,3);
//遍历arr1
for (int i = 0; i < arr1.length; i++) {
System.out.println(arr1[i]);
}/*
0,0,0,1,2,3,0,0,0,0
*/
}
@Test
public void test04(){
Properties properties = System.getProperties();
System.out.println(properties);
}
@Test
public void test03(){
System.out.println("hello");//普通信息的输出流 println方法不是System类的是out对象,out对象是java.io.PrintStream类型
System.err.println("java");//标准的错误输出流
Scanner input = new Scanner(System.in); //默认代码键盘输入
input.close();//按照规范来说,使用完输入流之后,需要关闭IO流
}
@Test
public void test02(){
Runtime.getRuntime().gc();//通知GC可以来回收一下内存垃圾,但是不代表GC立刻开始工作。
/*
特别是早期GC回收器,它会“stop the world"然后开始回收垃圾。
GC工作时,会让Java程序其他的代码停下来,等待GC工作完。
后期的JDK版本的GC回收器有优化,和Java程序并行。
高级部分再将GC算法。
*/
}
@Test
public void test01(){
Runtime runtime = Runtime.getRuntime();
System.out.println("OS给JVM分配的总内存:" + runtime.totalMemory());//512753664
System.out.println("JVM中空闲内存:" + runtime.freeMemory());//499328232
}
}
class MyClass{
private static final int a = 1;//没有set方法
public static int getA() {
return a;
}
}