日期类
我们用long类型的变量来表示时间,从基准时间往前几亿年,往后几亿年都能表示。如果想获得现在时刻的“时刻数值”,可以使用:
long now = System.currentTimeMillis();
这个“时刻数值”是所有时间类的核心值,年月日都是根据这个“数值”计算出来的。
Date类
在标准Java类库中包含一个Date类。它的对象表示一个特定的瞬间,精确到毫秒。在网上商城下单时,在对报销单进行审核时,都需要获取当前的时间,通过Date类就可以完成。
查看API文档大家可以看到其实Date类中的很多方法都已经过时了。JDK1.1之前的Date包含了:日期操作、字符串转化成时间对象等操作。JDK1.1之后,日期操作一般使用Calendar类,而字符串的转化使用DateFormat类。
DateFormat类
DateFormat是一个抽象类,一般使用它的的子类SimpleDateFormat类来实现。主要作用就是把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。
需求1:网页注册,需要输入日期,在网页上输入的所有内容,xiaoming,23, 1999-12-23,1999/12/23,但是传送到后台接收到都是字符串 “xiaoming”, “23”, “1999-12-23”,“1999/12/23”,需要把字符串----->日期
需求2:注册成功后,在网页上显示日期,可以不同格式来显示"1999-12-23", “1999/12/23”,“1999年12月23日”,需要把日期----->字符串。
Calendar类
Calendar 类是一个抽象类,为我们提供了关于日期计算的相关功能,比如:年、月、日、时、分、秒的展示和计算。GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。
JDK8的新的日期类
针对JDK8以前的时间日期类设计的不足,比如不支持时区,线程不安全等,JDK8引入了java.time包来作为新的日期时间处理类。
其他常用类
Math类
java.lang.Math提供了一系列静态方法用于科学计算;其方法的参数和返回值类型一般为double型。
如果需要更加强大的数学运算能力,计算高等数学中的相关内容,可以使用apache commons下面的Math类库。
Random类
Math类中虽然为我们提供了产生随机数的方法Math.random(),但是通常我们需要的随机数范围并不是[0, 1)之间的double类型的数据,这就需要对其进行一些复杂的运算。
如果使用Math.random()计算过于复杂的话,我们可以使用例外一种方式得到随机数,即Random类,这个类是专门用来生成随机数的,并且Math.random()底层调用的就是Random的nextDouble()方法。
枚举
JDK1.5引入枚举类型。枚举类型的定义包括枚举声明和枚举体。枚举体就是放置一些常量。
定义枚举要使用enum关键字。对于性别、季节、星期几等内容,如果定义为字符串类型,是很难限制其取值的。采用枚举可以轻松解决该问题。
所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的成员实质就是一个枚举类型的实例,他们默认都是public static final修饰的。可以直接通过枚举类型名使用它们。
注意
强烈建议当你需要定义一组常量时,使用枚举类型;
另外尽量不要使用枚举的高级特性
算法与数据结构
排序
排序(sorting)的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列
内部排序和外部排序
一类是整个排序过程在内存储器中进行,称为内部排序;
另一类是由于待排序元素数量太大,以至于内存储器无法容纳全部数据,排序需要借助外部存储设备才能完成,这类排序称为外部排序。
本章介绍的排序方法都属于内部排序
比较排序和非比较排序
大部分排序都是需要通过比较首先来判断大小,作为排序的依据的
但是也有例外的,比如计数排序、基数排序,不需要进行比较。效率可以做到更高,但是会有一些限制条件,也可能需要更多的空间
冒泡排序、选择排序、直接插入排序是最基本的三种排序,效率最低,但是算法简单。排序的学习一般从这三种排序算法开始。
冒泡排序
冒泡排序的算法
- 整个数列分成两部分:前面是无序数列,后面是有序数列
- 初始状态下,整个数列都是无序的,有序数列是空
- 如果一个数列有n个元素,则至多需要n-1趟循环才能保证数列有序
- 每一趟循环可以让无序数列中最大数排到最后,(也就是说有序数列的元素个数增加1)
- 每一趟循环都从数列的第一个元素开始进行比较,依次比较相邻的两个元素,比较到无序数列的末尾即可(而不是数列的末尾)
- 如果前一个大于后一个,交换
public class TestBubbleSort2{
public static void main(String [] args){
//定义一个无序数组
int [] arr = {75,87,56,45,89,100,76,34,89,97};
//排序前输出
System.out.println("排序前");
for(int score :arr){
System.out.print(score+"\t");
}
//排序
bubbleSort(arr);
//排序后输出
System.out.println("排序后");
for(int score :arr){
System.out.print(score+"\t");
}
}
public static void bubbleSort(int arr[]){
//大循环:n个元素排序,则至多需要n-1趟循环
int temp;
int i;
for(i=0;i<arr.length-1;i++){
//1. 假设有序
boolean flag = true;
//2.小循环:每一趟循环都从数列的前两个元素开始进行比较,比较到数组的最后
for(int j=0;j<arr.length-1-i;j++){
//如果前一个大于后一个
if(arr[j] > arr[j+1]){
//交换
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
//发生了交换,数组无序
flag = false;
}
}
//3.判断是否有序,有序,退出
if(flag){
break;
}
}
}
}
选择排序
选择排序的算法
- 整个数列分成两部分:前面是有序数列,后面是无序数列
- 初始状态下,整个数列都是无序的,有序数列是空
- 一共n个数,需要n-1趟循环(一趟都不能少)
- 每比较完一趟,有序数列数量+1,无序数列数量-1
- 每趟先假设无序数列的第1个元素(整个数列的第i个元素)是最小的,让当前的最小数,从第i+1个元素开始比较,一直比较到最后一个元素。如果发现更小的数,就假设当前数是最小数。
- 一趟比较完后,将发现最小数和无序数列的第一个数交换(如果最小数不是无序数列的第一个数)
public class TestSelectSort {
public static void main(String[] args) {
//给定无序的数组
int [] scoreArr = {75,87,56,45,89,100,76,34,89,97};
System.out.println(Arrays.toString(scoreArr));
//选择排序
selectSort(scoreArr);
System.out.println(Arrays.toString(scoreArr));
}
public static void selectSort(int[] scoreArr) {
//大循环:n个元素排序,则需要n-1趟循环
for(int i=0;i<scoreArr.length-1;i++){
//第i趟先假设第i个最小
int minIndex = i;
//从第i+1个元素开始,依次使用最小元素和每元素比较,一直比较到最后
for (int j = i+1; j <scoreArr.length ; j++) {
if(scoreArr[minIndex] > scoreArr[j]){
minIndex = j;
}
}
//一趟比较完后,或者最小值的索引,如果不是第i个,就交换
if(minIndex !=i){
int temp; temp = scoreArr[i];
scoreArr[i] = scoreArr[minIndex]; scoreArr[minIndex] = temp;
}
}
}
}
注意
- 冒泡排序最多需要n-1趟循环,最少1趟循环;选择排序必须进行n-1趟循环,一趟也不能少
- 冒泡排序中最多的操作就是比较和交换,一趟循环中可能发生多次交换;而选择排序中最多的操作是比较,一趟比较结束后如果发现更小的值才交换一次。
- 如果数组元素不是基本数据类型,而是对象,应该如何判断大小呢?可以让相应类实现Comparable接口并调用comparTo()方法进行比较。
- 快速排序是冒泡排序的完善版,都是基于交换的排序,是各种基于比较的排序算法中效率最高的,用到了分治和递归的思想。需要认真准备。