目录
一,集合体系结构
各个接口与实现类之间的关系
如下图:
Collection
List (有序集合,允许相同元素和 null )
LinkedList (非同步,允许相同元素和 null ,遍历效率低插入和删除效率高)
ArrayList (非同步,允许相同元素和 null ,实现了动态大小的数组,遍历效率高,用的多)
Vector (同步,允许相同元素和 null ,效率低)
Set (无序集合,不允许相同元素,最多有一个 null 元素)
HashSet( 无序集合,不允许相同元素,最多有一个 null 元素 )
Collection 是最基本的集合接口 ( 也可以称为顶级接口 )
在 Collection 的实例中,有些实例允许相同的元素,有些则不允许,还有一些能内置实现排序功能,所以 根据存储数据的方式(数据结构)各有不同,所以存储的容器也就有多种,从而形成了集合框架这一体系
同时,在 Java 中不提供直接继承自 Collection 的类, Java 所提供的类都是继承自 Collection 的 “ 子接口 ” : List和 Set
常用的方法
boolean add(Object o) 添加对象到集合
boolean remove(Object o) 删除指定的对象
int size() 返回当前集合中元素的数量
boolean contains(Object o) 查找集合中是否有指定的对象
boolean isEmpty() 判断集合是否为空
Iterator iterator() 返回一个迭代器
boolean containsAll(Collection c) 查找集合中是否有集合c中的元素
boolean addAll(Collection c) 将集合c中所有的元素添加给该集合
void clear() 删除集合中所有元素
void removeAll(Collection c) 从集合中删除c集合中也有的元素
void retainAll(Collection c) 从集合中删除集合c中不包含的元素
二、 List
特点:元素有序,且可重复
遍历:下标,foreach,迭代器
扩容:
初始容量10,负载因子0.5,扩容增量0.5倍
新容量 = 原容量 + 原容量 * 0.5
实现
1.ArrayList
简单数据结构,超出容量自动扩容,动态数组
内部实现是基于基础的对象数组的
随机访问快
不适合随机增加或删除
线程不安全
删除时的注意点
测试数据准备,为更好的显示问题,在构建的List集合中有紧挨在一起的两个或两个以上的元素
list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(3);
list.add(4);
1. 下标循环删除方式1
for(int i = 0; i<list.size(); i++) {
if(list.get(i) == 3) list.remove(i);
}
思考
1. 如果重复的元素不是紧挨着的呢
2. 出现的原因是什么
2. 下标循环删除方式2
for(int i = 0; i < list.size(); i++) {
if(list.get(i) == 3) list.remove(i--);
}
思考
1. 如果重复的元素不是紧挨着的呢
2. 如果能正常运行,为什么?
3. 下标循环倒序删除
for(int i = list.size() - 1; i >= 0; i--) {
if(list.get(i) == 3) list.remove(i);
}
思考
1. 如果重复的元素不是紧挨着的呢
2. 为什么?
4. foreach循环删除
for(Integer e: list) {
if(e == 3) {
list.remove(e);
}
}
思考
1. List有紧挨的重复元素可以吗
2. 如果没有紧挨的重复元素呢
3. 如果删除的恰好是倒数第二个元素呢
4. 如果删除的不是倒数第二个元素呢
5. 出现以上的问题的原因是什么
6. 删除的参数是基本型的整数
list.remove(i)
思考
1. 如果将参数包装为对象呢
LinkedList
LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部
线程不安全
LinkedList可被用作堆栈(stack)【包括了push,pop方法】,队列(queue)或双向队列(deque)
以双向链表实现,链表无容量限制,允许元素为null,线程不安全
适合做随机的增加或删除
2.Vector
线程安全
并行性能慢,不建议使用
3.CopyOnWriteArrayList
写时复制
线程安全
适合于读多,写少的场景
写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array
比Vector性能高
最终一致性
实现了List接口,使用方式与ArrayList类似
三、Set
特点:无序,不重复
思考:如果对List容器中的元素去重?
遍历:foreach,迭代器
扩容: 初始容量16,负载因子0.75,扩容增量1倍
实现
1、HashSet
它存储唯一元素并允许空值
依据对象的hashcode来确定该元素是否存在
由HashMap支持
不保持插入顺序
非线程安全
性能参数:初始容量,负载因子
默认值: 初始容量16,负载因子0.75
示例:new HashSet<>(20, 0.5f);
思考
1. 如何给ArrayList集合去重
2. set有ArrayList中存在的通过下标删除,或foreach循环删除时的问题吗? 为什么
3. set是否存在List删除,传入整数需要区分是基本型还是对象型的问题,【例如:list.remove(2)】,为什么?
4. HashSet是如何实现的?
TreeSet
是一个包含有序的且没有重复元素的集合
作用是提供有序的Set集合,自然排序或者根据提供的Comparator进行排序
TreeSet是基于TreeMap实现的
示例:
测试数据
ts = new TreeSet<>();
ts.add(1);
ts.add(8);
ts.add(7);
ts.add(2);
ts.add(4);
ts.add(6);
ts.add(3);
1. 默认自然排序
for(Integer e: ts) {
System.out.println(e);
}
2. 自定义比较器
1. 通过构造函数传入比较器
TreeSet<Integer> tset = new TreeSet<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2 - o1;
}
});
2. 实现排序接口
public class Student implements Comparable<Student>{
private Integer sid;
private String name;
private int age;
//构造函数,getter,setter,hashCode,equals等方法省略
@Override
public int compareTo(Student o) {
// TODO Auto-generated method stub
return o.getAge() - this.getAge();
}
}
四、Map
特点:
无序,键值对,键不能重复,值可以重复,
键重复则覆盖,没有继承Collection接口
扩容:初始容量16,负载因子0.75,扩容增量1倍
遍历:
先获取所有键的Set集合,再遍历(通过键获取值)
取出保存所有Entry的Set,再遍历此Set即可
实现
1、HashMap
线程不安全,最常用,速度快
内部采用数组来存放数据
基本原理
put执行过程
Table数组中的的Node
链表结构示意图
红黑树结构示意图
流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。
HashTable
线程安全,不太常用
2、ConcurrentHashMap
线程安全,比HashTable性能高
TreeMap
key值按一定的顺序排序
添加或获取元素时性能较HashMap慢
因为需求维护内部的红黑树,用于保证key值的顺序
LinkedHashMap
继承HashMap
LinkedHashMap是有序的,且默认为插入顺序
当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了
Map<String, String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("name1", "josan1");
linkedHashMap.put("name2", "josan2");
linkedHashMap.put("name3", "josan3");
Set<Entry<String, String>> set = linkedHashMap.entrySet();
Iterator<Entry<String, String>> iterator = set.iterator();
while(iterator.hasNext()) {
Entry entry = iterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
System.out.println("key:" + key + ",value:" + value);
}
排序
java.lang.Comparable
java.util.Comparator
工具类
Collections
提供一组静态方法操作集合
Arrays
提供一组静态方法操作数组
五、 jdk8:stream
介绍
jdk8添加的一个新的功能,称之为流,可以以声明的方式来处理数据,提供一种对 Java 集合运算的方便处理方式
让程序员写出高效率、干净、简洁的代码
特点
可以方便的对集合进行并行操作,便于使用多核资源
惰性求值
不是数据结构,不保存数据
不会修改原来的数据源,将操作后的数据保存到另一个对象中
操作
中间操作(Intermediate)
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 skip、 parallel、 sequential、 unordered
最终操作(Terminal)
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、iterator
特点:
在一次聚合操作中,可以有多个Intermediate,但是有且只有一个Terminal
使用示例
filter
sorted
distinct
min,max,count
group