集合
1、集合框架体系
单列集合
双列集合
2、单列集合
1、Collection接口和常用方法
collection接口实现特点
public interface Collection<E\> extend Iterable<E\>
collection 实现子类可以存放多个元素,每个元素可以是Object
有些Collection的实现类,可以存放重复元素,有些不可
有些Collection的实现类,有些是有序的(List),有些不是(Set)
Collection 接口没有直接的实现子类,是通过它的子接口Set和List来实现的
常用方法
add(); 添加单个元素
remove(); 删除指定元素
contains(); 查找元素是否存在
size(); 获取元素个数
isEmpty(); 判断是否为空
clear(); 清空
addAll(); 添加多个元素
containsAll(); 查找多个元素是否都存在
removeAll(); 删除多个元素
2、Collection 接口便利元素方式
使用 Iterator (迭代器)
Iterator 对象称为迭代器,主要用于遍历 Collection 集合中的元素
所有实现了Collection 接口的集合类都有一个 iterator()方法,用以返回一个实现了Iterator 接口的对象,即可以返回一个迭代器
Iterator 的结构图
注意:在调用iterator.next() 方法之前必须要调用iterator.hasNext() 进行检测,若不调用,并且下一条记录无效,直接调用iterator.next() 会抛出NoSuchElementException 异常。
Iterator 仅用于遍历集合,Iterator 本省并不存放对象
当再次使用迭代器时,需要重置迭代器
iteraator = col.ietrator();
快捷键:itit
显示所有快捷键的快捷键:Ctrl + j
增强 for 循环
增强for循环,可以代替iterator迭代器,特点:增强 for 就是简化版的iterator,本质一样。只能用于遍历集合数组
基本语法
for (元素类型 元素名: 集合名或数组名) {
访问元素
}
快捷键:I
3、List接口
基本介绍
List 接口时 Collection 接口的子接口
List 集合类中所有元素有序(即添加顺序和取出顺序一致)、且可重复
List 集合中的每个元素都有相应的顺序索引,即支持索引
List 容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
list.get(3)
JDK API 中 List 接口的实现类有
常用的有:ArrayList、LinkedList、Vector
常用方法
void add(int index,Object ele):在index位置插入ele元素
boolean addAll(int index,Collection eles):从index位置开始将eles中所有元素添加进来
Object get(int index):获取指定index位置的元素
int indexOf(Object obj):返回obj在当前集合中首次出现的位置
int lastIndexOf(Object obj):返回obj在当前集合中最后一次出现的位置
Object remove(int index):移除指定index位置的元素,并返回此元素
Object set(int index,Object ele):设置指定index位置的元素为ele,相当于是替换
List subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合 [fromIndex,toIndex)
1、ArrayList
ArrayList 的底层操作机制源码分析
ArrayList中维护了一个Object类型的数组elementData
transient Object[] elementData;
//transient 表示瞬间,短暂的,表示该属性不会被序列化当创建ArrayList对象时,如果使用的时无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如果需要再次扩容,则扩容elementData为1.5倍
如果使用的是直接指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍
2、Vector底层结构和源码刨析
基本介绍
Vector 类定义说明
Vector 底层也是一个对象数组,protected Object[] elementData;
Vector 是线程同步的,即线程安全,Vector类的操作方法带有 synchronied
在开发中,需要线程同步安全时,考虑使用Vector
扩容机制
如果是无参,默认10,满后,就按2倍扩容
如果指定大小,则每次直接按2倍扩容
3、LinkedList底层结构
说明
LinkedList 底层实现了双向链表和双端队列的特点
可以添加任意元素
线程不安全,没有实现同步
LinkedList 的底层操作机制
LinkedList 底层维护了一个双向链表
LinkedList 中维护了两个属性first和last分别指向首节点和尾节点
每个节点(Node对象),里面有维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表
所以LinkedList 的元素的添加删除,不是通过数组完成的,相对来说效率较高
4、ArrayList和LinkedList的比较
如何选择
改查操作多,选择ArrayList
增删比较多,选择LinkedList
一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList
在一个项目中,根据业务 灵活选择,也可能是这样,一个模块使用的是ArrayList,另一个模块是LinkedList
4、Set接口
Set接口基本介绍
无序(添加和取出顺序不一致),没有索引
不允许重复元素,所以最多包含一个null
JDK API 中Set接口的实现类有:
Set接口的常用方法
和List接口一样,Set接口也是Collection子接口,因此常用方法和Collection接口一样
Set接口的遍历方式
同Collection的遍历方式一样
不能用索引的方式来获取
1、HashSet
HashSet实现了Set接口
HashSet实际上是HashMap
可以存放null值,但是只能有一个null
HashSet不保证元素是有序的,取决于hash后,在确定索引的结果
不能有重复的元素/对象
HashSet 底层机制
HashSet 底层是(数组 + 链表 + 红黑树)
HashSet 底层是 HashMap
添加存储数据表table,看这个索引位置是否已经存放元素
如果没有,则直接加入
如果有,调用equals 比较,如果相同,就放弃添加,如果不同,则添加到最后
在Java8 中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64)就会进行树化(红黑树)
扩容机制
HashSet底层是HashMap,第一次添加时,table 数组扩容到16,临界值(threshold)是16*加载因子(loadFactor)是0.75 = 12
依照的是size(每加入一个元素,size 就会加 1)
如table 数组使用到了临界值 12,就会扩容到16*2=32,新的临界值就是32*0.75=24,以此类推
在Java8 中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64)就会进行树化(红黑树)
2、LinkedHashSet
LinkedHashSet说明
LinkedHashSet是HashSet的子类
LinkedHashSet 底层是一个LinkedHashMap,底层维护了一个数组 + 双向链表(LinkedHashSet 有 head 和 tail)
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的
LinkedHashSet 不允许添加重复元素
每个结点有 befor 和 after 属性,这样可以形成双向链表
在添加一个元素使,先求hash值,在求索引,确定该元素在hashtable的位置,然后添加的元素加入到双向链表(如果已经存在,不添加【原则和hashset一样】)
确保遍历LinkedHashSet 插入顺序和遍历顺序一致
5、Map接口
Map接口实现类特点
Map与Collection并列存在。用于保存具有映射关系的数据:Key - Value(双列元素)
Map 中的 Key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中
Map 中的 key 不允许重复(当有相同的 key ,就会替换),原因和 HashSet 一样
Map 中的 value 可以重复
Map 的 key 可以为 null ,value 也可以为 null,注意 key 为 null,只能有一个,value 为 null ,可以多个
常用 String 类作为 Map 的 key
key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
Map存放数据的 key-value示意图,一对 k-v 是放在一个Node中的,因为 Node 实现了 Entry 接口
解读
k-v 最后是HashMap$Node node = newNode(hash,key,value,null)
k-v 为了方便遍历,还创建 EntrySet 集合,该集合存放的元素的类型 Entry ,而一个 Entry 对象就有 k,v EntrySet<Entry<K,V>> 即: transient Set<Map.Entry<K,V>> entrySet;
entrySet 中,定义的类型是 Map.Entry,但实际上存放的还是 HashMap$Node ,因为 static class Node<K,V> implements Map.Entry<K,V>
当把 HashMap$Node 对象,存放到 entrySet 就方便我们遍历,因为 Map.Entry 提供了方法 K getKey(); V getValue();
Map接口常用方法
put:添加
remove:根据键(key)删除映射关系
get:根据键获取值
size:获取元素个数
isEmpty:判断个数是否为0
clear:清除
containsKey:查找键是否存在
Map接口遍历方法
containsKey:查找键是否存在
keySet:获取所有的键
entrySet:获取所有关系
vlaues:获取所有的值
HaspMap小结
HashMap 使Map 接口使用频率最高的实现类
HaspMap没有实现同步,因此线程是不安全的 ,方法没有做同步互斥的操作
HashMap底层机制及源码
扩容机制
HashMap 底层维护了Node 类型的数组table ,默认为null
当创建对象时将加载因子(loadfactor)初始化为0.75
当添加key-val时,通过key的哈希值得到在table的索引。然后 判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应的处理。如果添加时发现容量不够,则需扩容
第一次添加,则需要扩容table容量为16,临界值(threshold)为12
以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,及24,以此类推
再java8 中,如果一条链表的元素个数超过 TREEIFY_THRESHOLD(默认是 8),并且 table 的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
1、HashTable
HashTable 基本介绍
存放的元素是键值对:即 K - V
hashTable的键和值都不能为null
hashTable 使用的方法基本上和HashMap一样
hashTable 是线程安全的,hashMap 是线程不安全的
HashTable的底层
底层有数组 HashTable$Entry[] 初始化大小为 11
临界值 threshold 8 = 11 * 0.75
按照 int newCapacity = (oldCapacity << 1) + 1; 的大小扩容
2、Properties
基本介绍
Properties类继承自HashTable类并实现了Map接口,也是使用一种键值对的形式来保存数据
使用特点和HashTable类似
Properties 还可以用于 从 xxx.properties 问文件中,加载数据到Properties 类对象,并进行读取和修改,(xxx.properties 文件通常作为配置文件)
3、总结——开发中如何选择集合实现类
先判断存储的类型(一组对象【单列】 或 一组键值对【双列】
一组对象【单列】:Collection接口
允许重复:List
增删改查多:LinkedList【底层 维护了一个双向链表】
改查多:ArrayList【底层维护了 Object类型的可变数组】
不允许重复:Set
无序:HashSet【底层是HashMap,维护了一个哈希表,即(数组 + 链表 红黑树)】
排序:TreeSet
插入和取出顺序一致:LinkedHashSet,维护了数组 + 双向链表
一组键值对【双列】:Map
键无序:HashMap【底层是:哈希表 jdk7:数组 + 链表,jdk8:数组 + 链表 + 红黑树】
键排序:TreeMap
键插入和取出顺序一致:LingkedHashMap
读取文件:Proerties
4、Collection工具类
collection 工具类介绍
Collection 是一个操作 Set、List 和 Map 等集合的工具类
Collection 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作
排序操作:(均为static方法)
reverse(List):反转List中元素顺序
shuffle(Lise):对List 集合元素进行随机排序
sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
sort(List,Comparator):根据指定的 Comparator 产生的顺序对List 集合元素进行排序
swap(List,int,int):将指定List 集合中的 i 出元素和 j 处元素进行交换
查找、替换
Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
Object max(Collection,Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素出现的次数
void copy(List dest,List src):将src中的内容 复制到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值