集合
单列集合 Collection
List(增删改查):元素有序,可重复,有索引,有自带的索引
ArrayList 底层数据结构是数组,查询快,增删慢,线程不同步,效率比较高
Vectoer: 底层数据结构是数组,查询快,增删慢,线程同步,效率比较低
LinkedList 底层数据结构是链表,查询慢,增删快,线程不同步,效率高
这个集合有一些特有的方法addFist();addLast() getFirst();getLast()
removeFirst();removeLast() 获取并删除元素,
无元素将抛异常:NoSuchElementException
Set:元素无序,不可重复(底层是用了Map)
HashSet:底层结构是Hash表,线程不同步,高效
为什么能够实现不可重复;主要是根据元素的HashCode()方法和equals()方法,当在判断的时候首先判断两个元素的HashCode值是否相同,如果相同那么就判断equal的值是否返回的是true.如果是true,那就判定为相同,如果HashCode值相同那么就不会调用equals方法
结果:本来有六个对象的 但最后发现是有重复的
[Student[name=易建联, age=30],
Student[name=林书豪, age=28],
Student [name=詹姆斯,age=31],
Student [name=科比,age=38],
Student[name=林书豪, age=28]]
TreeSet:底层结构是二叉树,可对元素进行排序,默认是自然排序
自然排序: 自然排序就是按字母书序排序 是对象的话 利用对象的属性来判断
比如 a->b->c.....
0->1->2->3....
如果是字符串那么会按一个个的字母排序如果相等就比较下一个位置的字符,知道比出大小位置
比如 abc->acd->ace->ade.......
为什么能够实现不重复: Comparable接口的compareTo方法的返回值
比较器:两种
(1) 元素自身实现Comparable重写compareTo()方法
(2) 创建集合的时候传进去一个构造器 实现Comparator接口覆盖 compare方法 先比较主要因素 在比较次要因素
(3) 两种方法都存在的时候以比较器为主
LinkedHashSet:底层是利用LinkedHashMap将Key的值置为null就是LinkedHashSet了
双列结合 Map
HashMap
从上图可以看出来HashMap是Y轴方向是内存地址连续的数组,X周方向是长度不定,地址不连续的链表
HashMap的工作原理;
(1) 首先判断Key是否为null,如果为null,直接查找Table[0],如果不是null,先计算Key的HashCode,然后经过二次Hash.得到Hash值,这里的Hash值是一个int值
(2) 根据Hash值,找到对应的数组具体对Entry的长度求余,拿到索引
(3) 找到了对应的数组,就是找到了所在的链表,然后按照链表的操作对Value进行查找,插入,删除
一个实体是有:二次Hash值 key,Value,Next四部分组成的
put()过程:
(1) 如果key是null的话,默认就存储到Table[0]对应的链表了,遍历链表中的每个节点,如果发现其中存在节点Entry的key的值为null,那就替换为新的Value值,然后将旧的Value值返回,如果没发现的话就增加新的节点.
(2) 如果不为null的话,先计算key的hashCode值,再用计算的结果二次hash,将对应数组的索引i给找到(对实体的数量求余)
(3) 然后遍历table[i]为头节点的链表,如果发现有节点的Hash.key都相同的节点时,就替换新的Value,返回旧的value
get()过程:
get的过程大致和put过程一样,只是处理结果不一样,这里有一个隐患,因为HashMap是非线程安全的,如果在查找链表的过 程中, 突然另一个线程进来将对应的Entry删除了,那就GG了,他会一直在那循环,找啊找 最后导致的效果就是代码效率低,CPU很高
size()过程:HashMap的大小就很简单了,他不是实时计算的,是每次增加一个实体,size的数量就增加,需要的时候将这个值返回就行
TreeMap: 底层数据结构时二叉树,不同步,可排序
LinkedHashMap
事实上LinkedHashMap是HashMap的直接子类,二者唯一的区别是LinkedHashMap在HashMap的基础上,采用双向链表(doubly-linked list)的形式将所有entry连接起来,这样是为保证元素的迭代顺序跟插入顺序相同。上图给出了LinkedHashMap的结构图,主体部分跟HashMap完全一样,多了header指向双向链表的头部(是一个哑元),该双向链表的迭代顺序就是entry的插入顺序。
除了可以保迭代历顺序,这种结构还有一个好处:迭代LinkedHashMap时不需要像HashMap那样遍历整个table,而只需要直接遍历header指向的双向链表即可,也就是说LinkedHashMap的迭代时间就只跟entry的个数相关,而跟table的大小无关
集合的遍历方式
List集合中可以有不借助迭代器来读取数据
因为List集合是有索引的 也可以根据get(index)和size()方法来进行遍历
Map结合的遍历方式
Map集合两种取出方式:
第一种:Set<K> keySet()
取出Map集合中的所有键放于Set集合中,然后再通过键取出对应的值
Set<String> keySet = map.keySet();
Iterator<String> it =keySet.iterator();
while(it.hasNext()){
Stringkey = it.next();
Stringvalue = map.get(key);
//…..
}
第二种:Set<Map.Entry<K,V>> entrySet()
取出Map集合中键值对的映射放于Set集合中,然后通过Map集合中的内部接口,然后通过其中的方法取出
Set<Map.Entry<String,String>>entrySet = map.entrySet();
Iterator<Map.Entry<String,String>>it = entrySet.iterator();
While(it.hasNext()){
Map.Entry<String,String>entry = it.next();
Stringkey = entry.getKey();
Stringvalue = entry.getValue();
//……
}
并发修改异常
当在集合在利用迭代器遍历的过程中修改了集合中元素 那么就会发生并发修改异常
解决方式:
(1) 利用List集合的特有方法
(2) 利用List 特有的迭代器ListIiterator
集合工具类(Collections):
Collections:操作集合(一般是list集合)的工具类。方法全为静态的
sort(List list);对list集合进行排序; sort(List list, Comparator c) 按指定比较器排序
fill(List list, T obj);将集合元素替换为指定对象;
swap(List list, int I, int j)交换集合指定位置的元素
shuffle(List list); 随机对集合元素排序
reverseOrder() :返回比较器,强行逆转实现Comparable接口的对象自然顺序
reverseOrder(Comparator c):返回比较器,强行逆转指定比较器的顺序