集合
集合主要是两组(单列集合, 双列集合)
Collection
Vector,ArrayList,LinkedList
TreeSet,HashSet
Collection 接口有两个重要的子接口 List, Set , 他们的实现子类都是单列集合
Collection接口常用方法 add:添加单个元素 remove:删除指定元素 contains:查找元素是否存在 size:获取元素个数 isEmpty:判断是否为空 clear:清空 addAll:添加多个元素 containsAlI:查找多个元素是否都存在 removeAll:删除多个元素
Collections工具类:
介绍:
1)Collections是一个操作Set,List和Map等集合的工具类
2)Collections中提供了一系列静态的方法对集合元素进行排序
排序操作(均为static方法) 1.reverse(List):反转 List中元素的顺序 2.shuffle(List):对List 集合元素进行随机排序 3.sort(List):根据元素的自然顺序对指定List 集合元素按升序排序 4.sort(List, Comparator):根据指定的Comparator产生的顺序对List集合元素进行排序 5.swap(List, int, int):将指定list 集合中的i处元素和j处元素进行交换
查找,替换 1.Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素 2.Object max(Collection, Comparator):根据Comparator 指定的顺序,返回给定集合中的最大元素 3.Object min(Collection) 4.Object min(Collection,Comparator) 5.int frequency(Collection, Object):返回指定集合中指定元素的出现次数 6.void copy(List dest,List src):将src中的内容复制到dest中 7.boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换 List 对象的所有旧值
List
List:
List接口 常用方法 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 lastIlndexOf(Object obj):返向obj在当前集合中未次出现的位置Object ; remove(int index):移除指定index位置的元素,并返回此元素; Object set(int index, Object ele):设置指定index位者的元素为ele ,相当于是替换; List subList(int fromlndex, int tolndex):返回从fromIndex到tolndex位置的子集合
ArrayList的底层原理机制:
1)ArrayList中维护了一个Object类型的数组elementData.transient Object[] elementData; //transient 表示瞬间,短暂的,表示该属性不会被序列化 2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。 3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
Vector的基本介绍:
1)Vector类的定义说明 public class vector<E> extends AbstractList<E> implements List<E>,RandomAccess,cloneable,Serializable 2)Vector底层也是一个对象数组,protected Object[] elementData; 3)Vector是线程同步的,即线程安全,Vector类的操作方法带有synchronized 3)在开发中,需要线程同步安全时,考虑使用Vector 4)如果是无参构造,则初始elementData容量为10,若容量满后就按2倍扩容;如果是指定大小,则每次直接按2倍扩容。
LinkedList的全面说明:
1)LinkedList底层实现了双向链表和双端队列特点
2)可以添加任意元素(元素可以重复),包括null 3)线程不安全,没有实现同步
LinkedList的底层操作机制
1)LinkedList底层维护了一个双向链表 2)LinkedList中维护了两个属性first和last分别指向首节点和尾节点 3)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表 4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
Set
基本介绍:
1)无序(添加和取出的顺序不一致),
2)没有索引[后面演示]不允许重复元素,所以最多包含一个null
HashSet的全面说明:
-
HashSet实现了Set接口
-
HashSet实际上是HashMap //HashMap的底层是 数组+链表+红黑树
-
可以存放null值,但是只能有一个null
-
HashSet不保证元素的有序,取决于hash后,再确定索引的结果
-
不能有重复的元素/对象
HashSet底层原理机制:
1)HashSet底层是HashMap 2)添加一个元素时,先得到hash值-会转成->索引值 3)找到存储数据表table,看这个索引位置是否已经存放的有元素,如果没有,直接加入,如果有,调用equals比较,如果相同,就放弃添加。如果不相同,则添加到最后 4)在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY CAPACITY(默认64).就会进行树化(红黑树)。 //table表扩容是按两倍扩 注意: /*add方法里面调用put方法,该方法会执行hash(key)得到key对应的hash值,并不是直接通过hashCode()得到的,而是通过算法h = (key.hashCode()) ^ (h >>> 16)得到的*/ /*HashSet底层是HashMap,第一次添加时, table数组扩容到16,临界值(threshold)是16*加载因子 (loadFactor)是0.75 = 12 如果table数组使用到了临界值12,就会扩容到16* 2 =32,新的临界值就是32*0.75 = 24,依次类推*/ /*在Java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制*/
LinkedHashSet的全面说明:
-
LinkedHashSet是HashSet的子类
-
LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个数组+双向链表
-
LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(图),这使得元素看起来是以插入顺序保存的。
-
LinkedHashSet 不允许添重复元素。
LinkedHashSet的底层机制:
1)在LinkedHastSet 中维护了一个hash表和双向链表 (LinkedHashSet有head 和tail) 2)每一个节点有before和after属性,这样可以形成双向链表 3)在添加一个元素时,先求hash值,在求索引.确定该元素在table的位置,然后将添加的元素加入到双向链表 (如果已经存在,不添加[原则和hashset一样])
TreeSet:
TreeSet的底层就是TreeMap
Map
HashMap,TreeMap,HashTable,LinkedHashMap,Propertis
Map 接口的实现子类 是双列集合, 存放的K-V
Map 集合的遍历与 List 和 Set 集合不同。Map 有两组值,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。Map 以及实现 Map 的接口类(如 HashMap、TreeMap、LinkedHashMap、Hashtable 等)都可以用以下几种方式遍历。
1.在 for 循环中使用 entries 实现 Map 的遍历(最常见和最常用的)。 public static void main(String[] argz){ Map<String,String> map = new HashMap<String,String>() ; map.put("Java”,"123"); map. put("c语言”,"123"); for (Map.Entry<String,String> entry : map.entrySet()) { String mapKey = entry.getKey() ; String mapvalue = entry.getvalue() ; System.out.println(mapKey + ":" + mapvalue) ; } } 2.使用 for-each 循环遍历 key 或者 values,一般适用于只需要 Map 中的 key 或者 value 时使用。性能上比 entrySet 较好。 3.使用迭代器(Iterator)遍历 注意,源码分析: 1)k-v最后是 HashMap$Node node = newNode(hash,key,value,null) 2)k-v为了方便础序员的遍历,还会创建 EntrySet集合,该集合存放的元素的类型Entry,而一个Entry对象就有k, v EntrySet<Entry<K,V>>即:transient Set<Hap.Entry<K,V>> entrySet; 3)entrySet中,定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node 这是因为 static class Node<K, V> implements Map. Entry<K, V> 4)当把 HashMap$Node 对象存放到entrySet就方便我们的遍历
map:
map接口常用的方法: put:添加。 remove:根据键删除映射关系。 get:根据键获取值。 size:获取元素个数。 isEmpty:判断个数是否为0。 clear:清除。 containsKey:查找键是否存在。 keySet:获取所有的键 entrySet:获取所有关系 values:获取所有的值
HashMap底层机制:
1)HashMap底层维护了Node类型的数组table,默认为null 2)当创建对象时,将加载因子(loadfactor)初始化为0.75 3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换val; 如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容 调用resize()。 4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12 (16*0.75) 5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推 6)在Java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),粗table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
HashTable的基本介绍:
-
底层有数组Hashtable$Entry[] 初始化大小为11
-
第一次临界值 threshold为8 (11*0.75)
1)存放的元素是键值对:即K-V 2)hashTable的建和值都不能为null 3)hashTable使用方法基本上和HashMap一样 4)hashTable是线程安全的,hashMap是线程不安全的
Propertis基本介绍
1)Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。 2)他的使用特点和Hashtable类似 3)Properties还可以用于从 xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改