常用类——基础
1.String类的不可变性
String是指向常量池里的数据,对这个数据我们不能进行任何修改,要修改都是要新造一个数据。
2.String,StringBuffer,StringBuilder
底层都是char数组
-
String:不可变的字符序列,对内存消耗较大,关键字final
-
StringBuffer:可变的字符序列,效率高于String,低于StringBuilder,线程安全,涉及到安全问题
-
StringBuilder:线程不安全,适合用在多线程或者非共享数据上
3.String常用方法
length()、charAt()、equals()、compareTo()、startsWith()、endsWith()、contains()、indexOf()、getBytes()、toCharArray()、valueOf()
- Date
1.SimpleDateFormat:JDK8之前
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//解析:将字符串转化为日期
java.util.Date date = sdf.parse("2018-08-16")
2.DateTimeFormatter:JDK8
DateTimeFormatter dtf = DateTimeFormatte.ofPattern("yyyy-MM-dd");
//解析:将字符串转化为日期
Date date = dtf.parse("2018-08-16")
编码:字符串-》字节数据
解码:字节-》字符串
格式化:日期-》字符串 format
解析:字符串-》日期 parse
- 自然排序和定制排序
-
Comparable 自然排序 ,实体类实现Comparable接口,可以去重写compareTo()方法,解决实际排序问题。 把元素放进去,就会自动的调用CompareTo方法
-
Compartor第三方的比较器接口, 用法:实现这个接口,重写compare()方法。
- Collection
1.集合框架的概述
集合、数组都是对多个数据进行存储操作的结构,简称java容器。(此时的存储主要指的是内存层面的存储,不涉及持久化存储
2.数组存储
2.1 数组在存储多个数据方面的特点
-
一旦初始化以后,长度就确定了
-
数组一旦定义好,元素的类型就确定了
2.2 数组在存储多个数据方面的缺点
-
一旦初始化后,长度不可修改
-
数组中提供的方法非常有限,对于增删插入数据等操作非常不便,执行效率不高
-
获取数组中实际元素的个数的需求,没有现成的属性或方法可用
-
数组存储数据的特点:有序可重复,对于无序不可重复的需求无法满足
3.集合框架
Collection接口:单列集合,用来存储一个一个的对象
-
List接口:存储有序的,可重复的数据 -->“动态”数组
-
ArrayList、LinkedList、Vector
-
-
Set接口:存储无序的、不可重复的数组
-
HashSet、LinkedHashSet、TreeSet
-
Map接口:双列集合、用来存储键值对数据
-
HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
4.Collection和Collections的区别
Collection是集合类的上级接口,继承与他的接口主要有Set 和List. Collections是操作集合和map的工具类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
- Collection子接口一:List接口
1.List的实现类的结构
Collection接口:单列集合、用来存储一个一个的对象
-
List接口:存储有序的、可重复的数据 -->”动态“数组
-
ArrayList:作为List接口的主要实现类:线程不安全的、效率高,底层使用Object[] elementData存储
-
LinkedList:对于频繁的插入删除操作,使用此类效率比ArrayList高,底层使用双向链表存储
-
Vector:作为List接口的古老实现类:线程安全的、效率低,底层使用Object[] elementData存储
-
-
Set接口
2. ArrayList的底层实现原理
2.1 jdk7情况下
ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
list.add(123);//elementData[0] = new Integer(123);
...
list.add(11);//如果此次的添加导致底层数组容量不够,则扩容。默认扩容1.5倍,同时将原有数组复制到新数组中。
结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity);
2.2 jdk8中的变化
只有第一次调用add()时,底层才创建了长度为10的数组,并将数据添加到数组中,节省了内存。
3.LinkedList的底层实现原理
LinkedList list = new LinkedList();//内部声明了Node类型的first和last属性,默认值为null
list.add(123);//将123封装到Node中,创建了Node对象
4.Vector的底层实现原理
jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组,在扩容时,默认扩容为原来的数组长度的2倍。
- 集合——Map接口
1.Map的实现类的结构
Map:双列数据,存储key-value对的数据
-
HashMap:作为Map的主要实现类;线程不安全,效率高,可以存储null的key和value。底层:数组+链表(jdk7及之前);数组+链表+红黑树(jdk8)
-
LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历,原因:在原有的HashMap底层结构基础上,添加了一对指针,只想前一个和后一个元素。对于频繁的遍历操作,执行效率高于HashMap。
-
-
TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序或定制排序。底层使用红黑树
-
Hashtable:作为古老的实现类,线程是安全的,效率低,不能存储null的key和value
-
Properties:常用来处理配置文件,key和value都是String类型
-
2.Map结构的理解
Map中的key:无序的、不可重复的,使用Set存储所有的key -> key所在的类要重写equals()和HashCode()方法(以HashMap为例)
Map中的value:无序的、可重复的、使用Collection存储所有的value -> value所在的类要重写equals()
一个键值对:key-value构成了一个Entry对象
Map中的Entry:无序的、不可重复的,使用Set存储所有的Entry
3.HashMap的底层实现原理(jdk7)
1.HashMap map = new HashMap();
在实例化以后,底层创建了长度是16的一维数组,类型为Entry[]名字为table。
2.map.put(key1,value1);
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算之后,得到在Entry数组中的存放位置。
如果此位置上数据为空,此时添加成功。-------情况1
如果此位置上的数据不为空(意味着此位置上存在一个或多个数据<以链表形式存在>),比较key1和已经存在的一个或多个数据的哈希值:
如果都不相同,此时添加成功。--------情况2
如果和某一个已经存在的数据(key2,value2)的哈希值相同,继续比较:调用key1所在类的equals(key2)方法,比较:
如果返回false:添加成功。 --------情况3
如果返回true:使用value1替换value2。
补充:关于情况2和情况3,此时key1-value1和原来的数据以链表的形式存储。
3.在不断的添加过程中,会涉及到扩容问题,当超出临界值且存放的位置非空时进行扩容,默认的扩容方式,扩容为原来的2倍,并将原有的数据复制过来。
jdk8相较jdk7的不同:
1.new HashMap():底层没有创建一个长度为16的数组,首次调用put()时才创建
2.jdk8底层的数组是Node[]而不是Entry[]
3.jdk8中的底层结构:数组+链表+红黑树
当数组的某一个索引位置上的的元素以链表形式存在的数据个数>8且当前数组的长度>64时,此时索引位置上的所有数据改为用红黑树存储,提高比较时的效率
枚举类:类中的对象个数是确定的,有限个
枚举类的对象声明的修饰符:public static final
元注解:对现有的注解进行解释说明的注解
Retention:指明所修饰注解的生命周期
-
SOURCE:注解仅存在于源码中,在class字节码文件中不包含
-
CLASS:默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
-
RUNTIME运行时:注解会在class字节码文件中存在,解释运行后将类的结构加载到内存中,在运行时可以通过反射获取到
Target:指明注解修饰的对象范围,Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)
throw和throws的区别:
-
throw:手动生成一个异常对象并抛出,使用在方法内部
-
throws:处理异常的方式,使用在方法声明处的末尾
4.map的遍历
-
在增强for循环中使用entries实现Map遍历
for(Map.Entry<String, String> entry : map.entrySet()){
String mapKey = entry.getKey();
String mapValue = entry.getValue();
System.out.println(mapKey+":"+mapValue);
} -
在增强for循环中遍历key或value
//key
for(String key : map.keySet()){
System.out.println(key);
}
//value
for(String value : map.values()){
System.out.println(value);
} -
通过Iterator遍历
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
Entry<String, String> entry = entries.next();
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+":"+value);
} -
通过键找值遍历
for(String key : map.keySet()){
String value = map.get(key);
System.out.println(key+":"+value);
}