Java基础
一、ArrayList
ArrayList底层数组默认初始化容量为10。
- jdk1.8中ArrayList底层先创建一个长度为0的数组。
- 当第一次添加元素,调用add方法之后,会初始化一个长度为10的数组。
ArrayList容量使用完之后,需要对容量扩容。
- ArrayList容量是用完之后,会自动创建容量更大数组,将原先数组所有元素拷贝过去,导致效率变低。
- 优化:可以利用构造方法ArrayList(int capacity)或者ensureCapacity(int capacity)提供一个初始化容量,避免开始就扩容。
ArrayList构造方法
- ArrayList():创建一个初始化容量10的空列表。
- ArrayList(int capacity):创建一个指定初始化容量的空列表。
- ArrayList(Collection<?extends E>c):创建一个包含指定集合所有元素的列表。
ArrayList特点:
优点
- 向ArrayList末尾添加元素,add方法,效率很高。
- 查询效率很高。
缺点
- 扩容导致效率变低,可以指定初始化容量,在一定程度上改善。
- 另外数组无法存储大数据量,很难找到一块很大的连续内存空间。
- 向ArrayList中添加元素add,需要移动元素,效率较低;
若增删操作较多,考虑链表数据结构。Java实现链表
二、LinkList
LinkList特点
数据结构:LinkedList底层是一个双向链表,Java双向链表实现
优点:增删效率高。
缺点:查询效率低。
LinkedList也有下标,但是内存不一定连续,类似C++重载[]符号,将循位置访问模拟为循秩访问。
LinkedList可以调用get方法,返回链表中index元素。
但是每次查找都需要从头开始遍历。
LinkedList源码
add方法:
ListIterator接口
- LinkedList.add方法只能够把数据添加到链表末尾。
- 若要把对象添加到链表中间位置,则需要使用ListIterator接口的add方法;
- Iterator中remove方法,调用next之后,remove方法删除的是迭代器左侧的元素,类似键盘backspace。
- 调用previous之后,remove删除的是迭代器右侧元素。
- ListIterator中add方法,调用next之后,迭代器左侧添加一个元素;调用previous之后,add是迭代器右侧添加元素。
三、Vector
vector底层是数组。
初始化容量是10。
扩容:原容量使用完之后,会进行扩容,新容量扩大至原始容量的大概2倍。
vector是线程安全的,方法都带有synchronized关键字,高并发
synchronized概述。
提问,如何把ArrayList变成线程安全的?
调用Collections工具类中的static List synchronizedList(List list)方法。
Set
泛型:
- jdk1.5引入,之前都利用的Object[]。
- 使用Object[]缺点如下:
获取一个值必须进行强制类型转换。
调用一个方法前必须使用instance of判定对象类型。
泛型好处:
- 减少了强制类型转换次数,获取数值更加方便。
- 类型安全,调用方法更加安全。
- 泛型只会在编译时期起到作用,运行阶段JVM看不见泛型类型,JVM只能看见对应的原始类型,进行了类型擦除。
- 带泛型的类型,在使用是没有指定泛型类型,默认object。
List list = new HashTestArrayList(); //默认放任意object类型
- lambda表达式。
HashSet
特点:无序,没有下标,不可以重复。
TreeSet
TreeSet无序,不可以重复,但是可以排序。
HashSet为HashMap的key部分;TreeSet是TreeMap的key部分。
重点掌握HashMap和TreeMap。
HashMap
TreeMap
Map
- Map和Collection没有继承关系。
- Map以k,v键值对形式存储数据,k和v都是存储对象的内存地址(引用)。
Map常用接口方法如下:
注意
Map.Entry<K, V>是Map的一个接口,接口内部默认public static的。
Map的第一种遍历形式
第一类方法
先获取map的keySet,取出key对应的value。
特点:
效率相对较低,还要根据key从哈希表查找对应value;
通过foreach遍历map.keySet(),取出对应value:
或者通过迭代器遍历map.keySet(),取出对应value:
第二类方法
调用map.entrySet()方法,直接从entrySet获取key和value。
特点:
- 效率很高,直接从node节点获取key和value。
- 适用于大数据量map遍历。
或者调用map.entrySet(),利用foreach遍历entrySet:
最后一种调用map.entrySet(),使用迭代器遍历entrySet: