【Java基础】集合集
//多参照:http://cmsblogs.com/?cat=5 List之subList细节 1、subList返回的只是原列表的一个视图,它所有的操作最终都会作用在原列表上 2、生成子列表后,不要试图去操作原列表,否则会造成子列表的不稳定而产生异常 3、利用subList清除原列表中其中一部分,原因是子列表的操作都会反映在原列表上 public class LList { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); list.add(4); for(Integer i: list) System.out.print(i + " "); System.out.println(); //point3: 利用subList清除原列表中的其中一部分,原因是子列表的操作都会反映在原列表上 list.subList(0, 1).clear(); for(Integer i: list) System.out.print(i + " "); System.out.println(); //point1: subList返回的只是原列表的一个视图,它所有的操作最终都会作用在原列表上 List<Integer> sublist = list.subList(0, list.size()); //point2: 生成子列表后,不要试图去操作原列表,否则会造成子列表的不稳定而产生异常 list.add(5); for(Integer i: sublist) System.out.print(i + " "); } } Arrays.asList细节 1、在使用asList时不要将基本数据类型当做参数(个人认为指定List的泛型类型就可以避免明白该注意点) 2、不要试图改变asList返回的列表,该list是一个长度不可变的列表,传入参数的数组有多长,其返回列表就多长 public class LList { public static void main(String[] args) { int[] is = {2, 4, 6, 8, 10}; List list1 = Arrays.asList(is); // List<int[]> list1 = Arrays.asList(is); Integer[] its = {2, 4, 6, 8, 10}; List list2 = Arrays.asList(its); // List<Integer> list2 = Arrays.asList(its); System.out.println(list1.size() + "\t" + list2.size()); list2.remove(1); } } 集合之初始容量细节(List为例) JDK对List、Map的容量、加载因子的解释: 1、ArrayList实例都有一个容量 该容量是指用来存储列表元素的数组的大小,它总是至少等于列表的大小。随着向 ArrayList中不断添加元素,其容量也自动增长,并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单 2、HashMap的实例有两个参数影响其性能:初始容量和加载因子 容量是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。 加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。 当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。 其他:对于ArrayList和HashMap并不是线程安全的,故在使用的时候要注意该特点; public class LList { public static void main(String[] args) { int count = 10000000; //初始化的容量是10,(oldCapacity * 3)/2 + 1;扩容1.5倍 List<Integer> list1 = new ArrayList<Integer>(); List<Integer> list2 = new ArrayList<Integer>(count); long begin1 = System.currentTimeMillis(); for (int i = 0; i < count; i++) list1.add(i); long end1 = System.currentTimeMillis(); System.out.println("test 1 cost: " + (end1 - begin1)); for (int i = 0; i < count; i++) list2.add(i); long end2 = System.currentTimeMillis(); System.out.println("test 2 cost: " + (end2 - end1)); //test 1 cost: 1413 //test 2 cost: 279 } } List细节(Vector, ArrayList, LinkedList) +-----------------------------------------------------------------------------------------------------------------+ | Vector | +-----------------------------------------------------------------------------------------------------------------+ | Vector() | 构造一个空向量,使其内部数据数组的大小为 10,其标准容量增 | | | 量为零。 | | Vector(Collection<? extends E> c) | 构造一个包含指定 collection 中的元素的向量,这些元素按其 | | | collection 的迭代器返回元素的顺序排列。 | | Vector(int initialCapacity) | 使用指定的初始容量和等于零的容量增量构造一个空向量。 | | Vector(int initialCapacity, int capacityIncrement) | 使用指定的初始容量和容量增量构造一个空的向量。 | +-----------------------------------------------------------------------------------------------------------------+ |线程安全: Vector是同步; | |集合扩容:若capacityIncrement <= 0则扩大一倍,否则扩大至capacityIncrement。当然这个容量的最大范围为Integer.MAX_V | | ALUE即,2^32 – 1,所以Vector并不是可以无限扩充的。 | |底层实现:this.elementData = new Object[initialCapacity] | +-----------------------------------------------------------------------------------------------------------------+ | ArrayList | +-----------------------------------------------------------------------------------------------------------------+ | ArrayList() | 构造一个初始容量为 10 的空列表。 | | ArrayList(Collection<? extends E> c) | 构造一个包含指定 collection的元素的列表,这些元素是按照该 | | | collection 的迭代器返回它们的顺序排列的。 | | ArrayList(int initialCapacity) | 构造一个具有指定初始容量的空列表。 | +-----------------------------------------------------------------------------------------------------------------+ |线程安全:ArrayList是不同步; | |集合扩容:重新计算容量,newCapcity = (oldCapacity * 3) / 2 + 1; | |底层实现:this.elementData = new Object[initialCapacity] | +-----------------------------------------------------------------------------------------------------------------+ | LinkedList | +-----------------------------------------------------------------------------------------------------------------+ | LinkedList() | 构造一个空列表。 | | LinkedList(Collection<? extends E> c) | 构造一个包含指定 collection 中的元素的列表,这些元素按其 | | | collection 的迭代器返回的顺序排列。 | +-----------------------------------------------------------------------------------------------------------------+ |线程安全:LinkedList是不同步; | |集合扩容:增加新的节点 | |底层实现:header.next = header.previous = header; | +-----------------------------------------------------------------------------------------------------------------+ public class LList { public static void main(String[] args) { List<Integer> vector = new Vector<Integer>(); List<Integer> arraylist = new ArrayList<Integer>(); List<Integer> linkedlist = new LinkedList<Integer>(); int count = 100000; long bt = System.currentTimeMillis(); add(vector, count); long evt = System.currentTimeMillis(); System.out.println("vector add cost: " + (evt - bt)); add(arraylist, count); long eat = System.currentTimeMillis(); System.out.println("arraylist add cost: " + (eat - evt)); add(linkedlist, count); long elt = System.currentTimeMillis(); System.out.println("linkedlist add cost: " + (elt - eat)); System.out.println("======================================="); read(vector); long rvt = System.currentTimeMillis(); System.out.println("vector read cost: " + (rvt - elt)); read(arraylist); long rat = System.currentTimeMillis(); System.out.println("arraylist read cost: " + (rat - rvt)); read(linkedlist); long rlt = System.currentTimeMillis(); System.out.println("linkedlist read cost: " + (rlt - rat)); System.out.println("======================================="); delete(vector, count); long dvt = System.currentTimeMillis(); System.out.println("vector delete cost: " + (dvt - rlt)); delete(arraylist, count); long dat = System.currentTimeMillis(); System.out.println("arraylist delete cost: " + (dat - dvt)); delete(linkedlist, count); long dlt = System.currentTimeMillis(); System.out.println("linkedlist delete cost: " + (dlt - dat)); /* * vector add cost: 9 * arraylist add cost: 6 * linkedlist add cost: 5 * ======================================= * vector read cost: 8 * arraylist read cost: 8 * linkedlist read cost: 9 * ======================================= * vector delete cost: 1061 * arraylist delete cost: 1063 * linkedlist delete cost: 5 */ } } Map细节(HashMap、Hashtable、TreeMap) /* * +----E---> [C]LinkedHashMap * | * +---I---> [C]HashMap <---E---+ * [I]Map ---+---I---> [C]TreeMap <---E---+--- [C]AbstractMap <---I--- [I]Map * +---I---> [C]WeakHashMap <---E---+ * +---I---> [C]Hashtable <---E------- [C]Dictionary * * TreeMap -----> [I]NavigableMap --E--> SortedMap --E--> Map * TreeMap --E--> [C]AbstractMap -----> Map * TreeMap的key不能为null * * HashMap 和 Hashtable的异同点: * 相同点:都实现了Map、Cloneable、Serializable接口;底层都是基于单链表实现 * 不同点: 1.HashMap线程非安全;Hashtable线程安全 * 2.HashMap的key, value都可以为null;Hashtable的key, value都不能为null * 3.HashMap继承自AbstractMap;Hashtable继承自Dictionary * TreeMap的内部结构是一棵红黑树(又叫排序数,是二叉树的一种),使用链式存储,可以指定比较器Comparator,
* key需实现Comparable接口。key不能为null。存结点性能稍差,因为需要调整树结构;取结点用的是链表遍历,但
* 是属于有序比较,性能中等。迭代遍历时用的树的中序遍历,是一个有序序列。适用于有排序需求的情况。 */ public class LMap { public static void main(String[] args) { Map<String, String> hashmap = new HashMap<String, String>(); Map<String, String> hashtable = new Hashtable<String, String>(); Map<String, String> treemap = new TreeMap<String, String>(); int count = 100000; System.out.println("hashmap put cost: " + put(hashmap, count)); System.out.println("hashtable put cost: " + put(hashtable, count)); System.out.println("treemap put cost: " + put(treemap, count)); System.out.println("============================================"); System.out.println("hashmap read cost: " + read(hashmap)); System.out.println("hashtable read cost: " + read(hashtable)); System.out.println("treemap read cost: " + read(treemap)); System.out.println("============================================"); System.out.println("hashmap delete cost: " + delete(hashmap, count)); System.out.println("hashtable delete cost: " + delete(hashtable, count)); System.out.println("treemap delete cost: " + delete(treemap, count)); // hashmap put cost: 56 // hashtable put cost: 44 // treemap put cost: 49 // hashmap read cost: 16 // hashtable read cost: 19 // treemap read cost: 23 // hashmap delete cost: 37 // hashtable delete cost: 22 // treemap delete cost: 39 } }