java集合整理
一.什么是集合
集合类存放于java.util包中。
集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference)。
集合类型主要有3种:set(集)、list(列表)和map(映射)。
集合接口分为:Collection和Map,list、set实现了Collection接口
二.集合用法
List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。 ArrayList和数组类似,可以动态增长,动态增长的容量为(原容量X3)/2,根据实际存储的数据的长度自动增长List的长度。查找元素效率高是因为ArrayList随机读取的时候采用的是get(index),根据指定位置读取元素,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
一般工作中我们用到ArrayList最多,常用的方法比如:
void add(int index,E element ) 在列表的指定位置插入该元素;
Object get(int index) 返回集合index索引出的元素;
void remove(int index) 移除指定位置的元素;
void addAll(Collection<T>) 合并集合;
void clear() 清空集合;
Boolean contains(Object o)判断集合是否包含某元素。
LinkedList是基于双向链表实现的,除了当做链表使用外,它也可以被当作堆栈、队列或双端队列进行操作。不是线程安全的,继承AbstractSequentialList实现List、Deque、Cloneable、Serializable。LinkList在添加和删除元素时具有比ArrayList更好的性能效率较高.但在get与set方面弱于ArrayList,增删快读取慢。.这些对比都是指数据量很大或者操作很频繁的情况下的对比。它还实现了 Queue 接口,该接口比List提供了更多的方法,包括 offer(),peek(),poll()等。
Vector 和ArrayList类似数组实现, 区别在于Vector是同步类(synchronized)线程安全.因此,开销就比ArrayList要大,Vector每次扩容会增加一倍的空间,一般实际应用中用的较少。
Map集合使用键(key)值(value)来保存数据,其中值(value)可以重复,但键(key)必须是唯一,也可以为空,但最多只能有一个key为空,它的主要实现类有HashMap、LinkedHashMap、TreeMap。
Map接口的常用实现类有HashMap和TreeMap,HashMap类通过哈希码对其内部的映射关系进行快速查找,而TreeMap类中的映射关系存在一定的顺序,如果希望在遍历集合时是有序的,应该使用由TreeMap类实现的Map集合,否则建议使用由HashMap类实现的Map集合,因为由HashMap类实现的Map集合对于添加和删除映射关系更高效。
Map集合允许值对象为null,并且没有个数限制,因此当get()方法的返回值为null时,可能有两种情况,一种是在集合中没有该键对象,另一种是该键对象没有映射任何值对象,即值对象为null。因此,在Map集合中不应该利用get()方法来判断是否存在某个键,而应该利用containsKey()方法来判断。
Map集合允许值对象为null,并且没有个数限制,因此当get()方法的返回值为null时,可能有两种情况,一种是在集合中没有该键对象,另一种是该键对象没有映射任何值对象,即值对象为null。因此,在Map集合中不应该利用get()方法来判断是否存在某个键,而应该利用containsKey()方法来判断。
HashMap保存元素时先进后出、无序性;查询效率比较高;key-value可以为null,但最多只能为一个null;不支持线程同步,即可以有多个线程同时写HashMap,可能导致数据不一致,如果需要同步可以使用Collection的synchronizedMap方法使其同步。工作中经常使用HashMap进行存取值操作。值得注意的是通常对Map集合的遍历:
1、将map 集合中所有的键取出存入set集合, Set<K> keySet() 返回所有的key对象的Set集合 再通过get方法获取键对应的值。 2、 values() ,获取所有的值. 。
比较常用的HashMap方法如下:
1.put(K k,Value value);存值; 2.containsKey(Object k);判断是否存在对应的值; 3.containsValue(Value v);判断是否存在相应的值; 4.remove(Object k);移除该键值对; 5. clear();清除所有键值对
面试中经常问到HashMap的底层原理,都要有自己的理解。 首先有一个每个元素都是链表(可能表述不准确)的数组,当添加一个元素(key-value)时,就首先计算元素key的hash值,以此确定插入数组中的位置,但是可能存在同一hash值的元素已经被放在数组同一位置了,这时就添加到同一hash值的元素的后面,他们在数组的同一位置,但是形成了链表,同一各链表上的Hash值是相同的,所以说数组存放的是链表。而当链表长度太长时(链表长度大于8),链表就转换为红黑树(java8新特性),这样大大提高了查找的效率。当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的搬移到新的数组中。
Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换(几乎不用)。
LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序(使用很低)。
TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常(使用率低)。
原谅我这一生不羁放纵爱自由!