Collection接口
List接口
有序的(有前后顺序),可以使用下标来操作
通常允许重复元素
泛型不能使用基本数据类型
实现类
ArrayList类
可变数组,允许null,底层是基于数组实现的
ArrayList<String> list = new ArrayList<>();
//增
list.add("Java"); //追加到集合的尾部
list.add("C++");
list.add(1,"Python");
list.addAll(list); //添加一个集合到此集合中
list.addAll(1,list);
// 删
list.remove("Python"); //只会移除第一个与字符串相等的
list.remove(1);
list.clear(); //清除所有元素
//改
list.set(1,"JavaScript");
//查
String s = list.get(3);
ArrayList里的clone()方法返回的是此实例的浅表副本,为浅克隆
contains(Object o) List集合中是否包含o,true/false
ensureCapacity(int minCapacity) 手动扩容
isEmpty() 空true
lastIndexOf(Object o) 元素出现的最后一次的下标位置
removeRange(int fromIndex,int toIndex) 移除集合中[fromIndex,toIndex)区间内的所有元素
size() 返回元素数量
toArray() 变数组
trimToSize() 将集合容量调整至当前大小,手动减小容量
LinkedList类
是Deque接口的实现类
链表,线性数据结构,特点:内存不连续,节点分为两部分----数据域和指针域,节点之间通过指针域连接,大小不固定,可以任意扩充节点,亦可以使用下标访问,效率很低,添加删除元素效率快
Vector类
与ArrayList相比,Vector是线程同步的
大小可以根据需要增大或缩小
Stack类
栈,后进先出LIFO
是Vector的子类
push() 入栈
pop() 出栈
peek() 查看栈顶元素
遍历
- 循环生成下标
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
- 增强for循环/foreach
for (String s : list) {
System.out.println(s);
}
编译后的字节码文件
- 迭代器
所有实现了Iterable接口的对象,都可以使用迭代器进行遍历
作用:从集合中依次取出它的每一个元素,直到全部取完为止
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
注意
List<Integer> l = new ArrayList<>();
l.add(1);
l.add(2);
l.add(3);
//分别执行以下语句
Integer i = 1;
l.remove(i); //会移除1
l.remove(1); //会移除下标为1的数,即为2
Set接口
不允许重复元素,最多只能包含一个null
使用
声明,初始化
增删改查
遍历
- 迭代器遍历
**** 需要实现Iterable接口,会锁定集合,不允许直接操作集合,可以在迭代器上删除当前被迭代到的元素
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
- 增强for循环
所有实现了迭代器的类,都可以使用增强for循环遍历
for (String s : set) {
System.out.println(s);
}
- **注意
**在迭代器遍历中,不允许直接操作集合,例子如下
for (String s : set) {
if (s.equals("MySQL")){
set.add("SSM");
}
}
在以上代码中,会抛出异常ConcurrentModificationException
但是,可以在迭代器上,删除当前被迭代到的元素
实现类
HashSet类
是由哈希表(实际上是一个HashMap实例)支持,HashSet的值就是HashMap的键,HashMap的值是一个统一的对象
特点:
- 无序
- 允许null
HashSet<String> set = new HashSet<>();
set.add("Java");
set.add("C++");
set.add("Python");
//set.add方法还会返回一个boolean类型结果,判断是否添加成功
System.out.println(set.add("HTML");
set.clear(); //清除表中元素
set.clone(); //浅表克隆
set.contains(Object o);
set.isEmpty();
LinkedHashSet类
双向链表用来记录元素插入顺序
TreeSet类
树形结构,节点键没有前后关系
Queue接口(队列)
Deque接口(双向队列)
Map接口
每一个元素都是由key(键)-value(值)
保存时,需要根据key存储value
读取时,根据key读取value
键不能重复
实现类
HashMap类
hash映射:key通过哈希函数,计算出哈希地址,value保存在这个地址中
哈希函数有多种方式:
- 直接地址法
- 数字分析法
- 平方取中法
- 折叠法
- 除留余数法
- 随机数法
以上方式会哈希冲突,解决方法:
- 开放地址:线性探测,二次探测,伪随机数探测
- 再哈希法
- 链式地址法
- 公共溢出区
底层实现
构造
- 无参:初始容量默认16,加载因子默认0.75,门槛默认16*0.75=12
- 初始容量
- 初始容量+加载因子
- Map
table数组
创建与容量一样大小的数组
Hash中的桶
链表
解决哈希冲突的方式:链式地址法
冲突元素会放在一个链表中,当链表中元素个数>=8时,同时容量>=64,才会进行树化
红黑树
用来提升元素的查找效率(链表O(n)–>红黑树O(logn))
当红黑树的节点数<=6时,红黑树就会退化成链表
HashTable类
线程安全的,全局锁,锁整个哈希表
不允许null键和null值
LinkedHashMap类
HashMap的子类,迭代顺序就是key的插入顺序
TreeMap类
红黑树,根据key的自然顺序,比较器
迭代顺序就是key的自然顺序
ConcurrentHashMap类
线程安全的,分段锁,只锁操作的桶
并发执行效率更高
使用
声明
初始化
CRUD
遍历
HashMap<String,Float> map = new HashMap<>();
//增
map.put("Tom",100f);
map.put("Jack",59f);
map.put("Jerry",47f);
//删
map.remove("Tom");
map.clear();
//改
map.put("Jack",10f);
//查
System.out.println(map.get("Jack"));
System.out.println(map.size());
遍历
获取键
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key+":"+map.get(key));
}
获取值
Collection<Float> values = map.values();
for (Float value : values) {
System.out.println(value);
}
获取键值对
Set<Map.Entry<String,Float>> entries = map.entrySet();
for (Map.Entry<String,Float> entry : entries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}