Day14
今天了解一些其他API基本方法和集合框架中的ArrayList
1.日期时间API
Date:
大部分方法已被弃用了,java源码里推荐使用Calendar,但是Calendar也有其缺陷。Java 8中有新的时间和日期API更好用。
常用方法:
new Date():当前时间
getYear():是当前年份与1900年份之差,
getMonth():从0开始,比如1月得到0,
getDate():日期数(几号),getDay():星期几,getHours():小时 getMinutes():分钟 getSeconds():秒数。
日期格式化:只使用Date打印出的日期可读性很差。可以使用 SimpleDateFormat 对时间进行格式化,但 SimpleDateFormat 是线程不安全的。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd h:mm:ss");
System.out.println(sdf.format(new Date()));
其中,y代表年,大写M表示月,d表示天,h表示时,m表示分,s表示秒,-和:是分隔符可以自己定义。
Calendar:
该类被abstract所修饰,说明不能通过new的方式来获得实例,对此,Calendar提供了一个类方法getInstance,以获得此类型的一个通用的对象,getInstance方法返回一个Calendar对象(该对象为Calendar的子类对象),其日历字段已由当前日期和时间初始化:
Calendar c = Calendar.getInstance();
为什么说返回的是Calendar的子类对象呢,因为每个国家地区都有自己的一套日历算法,比如西方国家的第一个星期大部分为星期日,而中国则为星期一。
常用方法:
1.获取时间:
// 使用默认时区和语言环境获得一个日历
Calendar c = Calendar.getInstance();
// 赋值时年月日时分秒常用的6个值,注意月份下标从0开始,所以取月份要+1
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH) + 1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + c.get(Calendar.HOUR_OF_DAY));
System.out.println("分:" + c.get(Calendar.MINUTE));
System.out.println("秒:" + c.get(Calendar.SECOND));
2.set设置时间
Calendar c = Calendar.getInstance();
// 如果想设置为某个日期,可以一次设置年月日时分秒,由于月份下标从0开始赋值月份要-1
// cal.set(year, month, date, hourOfDay, minute, second);
c.set(2020, 2, 27, 23, 33, 33);
// 或者6个字段分别进行设置,由于月份下标从0开始赋值月份要-1
c.set(Calendar.YEAR, 2020);
c.set(Calendar.MONTH, 1);
c.set(Calendar.DAY_OF_MONTH, 27);
c.set(Calendar.HOUR_OF_DAY, 23);
c.set(Calendar.MINUTE, 33);
c.set(Calendar.SECOND, 33);
//打印
System.out.println(c.getTime());
3.add方法
add(int field, int amount)
前面是要添加的时间类型如Calendar.YEAR后面是要添加的大小,可以为负,代表向前推移。
4.getTimeInMillis():
会返回long型的整数 表示从格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000到Calendar对象表示的时间之间的毫秒数。
java.time:Java8新增的关于时间和日期的包
Java 8的日期和时间类包含 LocalDate、LocalTime、Instant、Duration 以及 Period,这些类都包含在 java.time 包中,Java 8 新的时间API的使用方式,包括创建、格式化、解析、计算、修改,
LocalDate 只会获取年月日,而且是格式化的。
// 创建 LocalDate
// 获取当前年月日
LocalDate localDate = LocalDate.now();
// 构造指定的年月日
LocalDate localDate1 = LocalDate.of(2019, 9, 12);
// 获取年、月、日、星期几
int year = localDate.getYear();
int year1 = localDate.get(ChronoField.YEAR);
Month month = localDate.getMonth();
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
int day = localDate.getDayOfMonth();
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
LocalTime 只会获取时分秒
// 创建 LocalTime
LocalTime localTime = LocalTime.of(14, 14, 14);
LocalTime localTime1 = LocalTime.now();
// 获取小时
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
// 获取分
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
// 获取秒
int second = localTime.getMinute();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
LocalDateTime 获取年月日时分秒,相当于 LocalDate + LocalTime
// 创建 LocalDateTime
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
LocalDateTime localDateTime3 = localDate.atTime(localTime);
LocalDateTime localDateTime4 = localTime.atDate(localDate);
// 获取LocalDate
LocalDate localDate2 = localDateTime.toLocalDate();
// 获取LocalTime
LocalTime localTime2 = localDateTime.toLocalTime();
2.System:
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
由于该类的构造方法是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员方法和成员变量都是static(静态)的,所以也可以很方便的调用他。
system中包含了in、out和err三个成员变量,分别代表标准输入流(键盘输入)、标准输出流(显示器)和标准错误输出流(显示器)。
public final static InputStream in;
//标准输入流
public final static PrintStream out;
//标准输出流
public final static PrintStream err;
//标准错误流
由此可见,system中的out和in都不是内部类,是成员变量。out是PrintStream的final static来修饰变量,由此可见,out是可以调用printStream中的方法的。例如,system.out.println中的println就是printStream中的一种输出方法。
常用方法:
1、System.arraycopy(a,b,c,d,e): 其中,a是被复制的数组,b是复制的起始位置,c是复制到的数组,d是复制到这个数组的起始位置,e是复制到这个数组的结束位置。
2、System.currentTimeMillis():返回毫秒数,之前new Date()所做的事情其实就是调用了System.currentTimeMillis()。返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
可以直接把这个方法强制转换成Date类型。
long currentTime = System.currentTimeMillis();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date2 = new Date(currentTime);
System.out.println(formatter.format(date2));
// 运行结果如下:
// 当前时间:2020-02-28 00:05:01
3.Math:
java.lang.Math 类提供了一些基本数字运算和几何运算的方法。此类中的所有方法都是静态的。这个类是 final 类,因此没有子类。
1.计算
Math.sqrt() : 计算平方根
Math.cbrt() : 计算立方根
Math.pow(a, b) : 计算a的b次方
Math.max( , ) : 计算最大值
Math.min( , ) : 计算最小值
Math.abs() : 取绝对值
2.进位
Math.ceil(): 天花板的意思,就是逢余进一
Math.floor() : 地板的意思,就是逢余舍一
Math.rint(): 四舍五入,返回double值。返回最接近参数的整数
注意:.5的时候会取偶数,就是如果有2个数同样接近,则返回偶数的那个。
它有两个特殊的情况:1)如果参数本身是整数,则返回本身。2)如果不是数字或无穷大或正负0,则结果为其本身。
Math.round(): 四舍五入,float时返回int值,double时返回long值。就是数学上的四舍五入。
3.随机数
Math.random(): 取得一个[0, 1)范围内的double类型随机数.
4.UUID:
java.util.UUID是jdk1.5之后新增的一个工具类,在java.util下,用它可以产生一个号称全球唯一的ID。
UUID含义是通用唯一识别码 (Universally Unique Identifier),这是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF)
的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。
UUID是一个128位长的数字,算法的核心思想是结合机器的网卡、当地时间、一个随即数来生成UUID。从理论上讲,如果一台机器每秒产生10000000个UUID,则可以保证(概率意义上)3240年不重复。
UUID由以下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。在ColdFusion中可以用CreateUUID()函数很简单地生成UUID,
其格式为:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。而标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (8-4-4-4-12);
UUID uuid = UUID.randomUUID();//UUID 中 public static randomUUID()方法
System.out.println(uuid);//随机生成a0ea48c5-9b7f-420e-bd00-d0d69e23f34a
5.Arrays:
Arrays类位于 java.util 包中,主要包含了操纵数组的各种方法
1.Arrays.fill(Object[] array, Object obj):用指定元素填充整个数组 (会替换掉数组中原来的所有元素)。
2.Arrays.sort(Object[] array):对数组元素进行排序 。
3.Arrays.binarySearch(Object[] array, Object key):使用二分法查找数组内指定元素的索引值
注意:在调用该方法之前,必须先调用 Arrays.sort() 方法进行排序,如果数组没有排序,那么结果是不确定的,此外如果数组中包含多个指定元素,则无法保证将找到哪个元素。
4.Arrays.copyOf(T[] original, int newLength):拷贝数组,其内部调用了 System.arraycopy() 方法,从下标 0 开始,如果超过原数组长度,则会用 null 进行填充新数组。
5.Arrays.equals(Object[] array1, Object[] array2):判断两个数组是否相等。
数组元素为基本数据类型时,依次比较值
数组元素为引用数据类型时,依次调用元素的 equals() 方法进行比较
即如果两个数组被认为是相等的,则两个数组中应包含相同顺序的相同元素
6.Arrays.toString(Object[] array):返回数组元素的字符串形式。
7.Arrays.asList(): 该方法是将数组转化成List集合的方法。
List list = Arrays.asList(“a”,“b”,“c”);
注意:
(1)该方法适用于引用型数据的数组(String、Integer…)
(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)
(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新
(4)不支持add()、remove()、clear()等方法,因为它的源码中没有定义。
(5)用此方法得到的List的长度是不可改变的。(只读)
所以:
如果要创建的List只是用来遍历,就用Arrays.asList()。
如果要创建的List还要添加或删除元素,只能new一个java.util.ArrayList,然后一个一个的添加元素。
集合框架(重点)
在日常的开发工作中,我们经常使用数组,但是数组是有很多的局限性的,比如:数组大小固定后不可修改,只能存储基本类型的值等等。
基于数组的这些局限性,Java框架就产生了用于解决此类问题的工具,即集合框架。
Java集合框架标准化了Java处理对象组的方式。Java集合框架在JDK1.2版本提出,在JDK1.5版本进行了修改(引入了泛型、自动装箱/拆箱以及for-each格式循环)。
概念:
集合框架:JDK提供的一系列接口及其实现,处理多个元素,提供数据结构的实现。
java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。
储存分类:
单元素
键值对
Java中有许多的集合框架类,基于这些类的共性特征,向上高度抽取,便形成了共性的集合框架接口-Collection。
Collection:集合中的根接口。
由于Collection是抽取了各集合的共性所形成的接口,所以所有的集合类都实现了此接口,此接口的特点如下:
1.它是用于存储对象的容器
2.可动态扩展容量
3.不能存储基本类型的值,当然你可以使用包装类去存储它。
Collection:
size():集合中元素的数量
isEmpty():判断集合是否为空
contains(Object o):判断是否包含指定的对象
toArray():返回对象数组
add():增加元素到集合中
emove(Object o);删除元素
containsAll():将指定集合中的所有元素添加到此集合中
addAll():一次增加多个元素到集合中
removeAll():一次删除多个元素
retainAll():保留
clear():清空
List extends Collection:
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
E get(int index):返回列表指定索引位置元素
E set(int index, E element):替换指定索引位置元素,返回旧元素。
void add(int index, E element):在列表指定索引位置添加元素。
E remove(int index):删除指定索引位置元素。
int indexOf(Object o):返回指定元素在列表中第一次出现的位置。如果列表不包含该元素,则返回-1。
int lastIndexOf(Object o):同上,不过返回最后一次出现的位置。
List subList(int fromIndex, int toIndex):返回该列表从索引位置fromIndex到toIndex元素的视图。注意,这里并不是创建了一个新列表,二者是同一引用。
ArrayList:ArrayList接口继承抽象类AbstractList,并且实现了List、RandomAccess、Cloneable和Java.io.Serializable接口。
内部使用的是Object数组存储数据,数组是可以动态扩容的,可以认为ArrayList是一个动态大小的数组, 通过索引查找元素,效率高
该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。
特点:
容量不固定,可以动态扩容。
元素可重复并且有序。
允许存储null值。
对于随机访问效率非常高,时间复杂度为O(1)。
对于添加和删除元素,需要移动数据,平均时间复杂度为O(n)。
相较LinkedList占用空间更小,不需要存储额外数据。
集合支持泛型,具体的类型称为类型参数,基本类型不可作为类型参数,可以使用对应的包装类。
可以通过以下博客了解更多关于集合框架的内容:
Java 集合框架总结(一)
Java 集合框架总结(二)