java从基础知识(七)java集合
一、集合类介绍
1、List(元素有放入顺序,可重复)
1.1、List的实现
1.1.1、ArrayList
ArrayList就是动态数组(需要连续的存储空间),用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,灵活的设置数组的大小等好处。在指定位置的查找效率较高,是非线程安全的。
public class Test { public static void main(String arg[]) { /** * ArrayList有3个构造方法 */ ArrayList al1 = new ArrayList(); System.out.println("构造一个初始容量为 10 的空列表 : " + al1.size()); ArrayList al2 = new ArrayList(12); System.out.println("构造一个具有指定初始容量的空列表 : " + al2.size()); al1.add("array"); al1.add("array1"); ArrayList al3 = new ArrayList(al1); System.out.println(" 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列 : " + al3.toString()); /** * ArrayList方法介绍 */ al1.add("array"); System.out.println("将指定的元素添加到此列表的尾部 : " + al1.get(0)); al1.add(1, "array2"); System.out.println("将指定的元素插入此列表中的指定位置 : " + al1.get(1)); al1.clear(); System.out.println(" 移除此列表中的所有元素 : " + al1.size()); al1.add("array"); System.out.println("如果此列表中包含指定的元素,则返回 true : " + al1.contains("array")); al1.ensureCapacity(3); System.out.println("如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数 : " + al1.size()); System.out.println("返回此列表中指定位置上的元素 : " + al1.get(0)); System.out.println("返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1 : " + al1.indexOf("array")); System.out.println("如果此列表中没有元素,则返回 true : " + al1.isEmpty()); System.out.println("返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1 : " + al1.lastIndexOf("array")); System.out.println("移除此列表中指定位置上的元素 : " + al1.remove(0)); al1.add("array"); System.out.println("移除此列表中首次出现的指定元素(如果存在),不存在则返回false: " + al1.remove("arr")); al1.set(0, "array1"); System.out.println("用指定的元素替代此列表中指定位置上的元素 : " + al1.get(0)); System.out.println("返回此列表中的元素数 : " + al1.size()); al1.add("array"); al1.trimToSize(); System.out.println("将此 ArrayList 实例的容量调整为列表的当前大小 : " + al1.size()); Object[] strArr = al1.toArray(); System.out.println("按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 : " + strArr.length + " " + strArr[0]); } }
ArrayList遍历
public class Test { public static void main(String arg[]) { ArrayList al = new ArrayList(); al.add("array1"); al.add("array2"); al.add("array3"); for(int i = 0; i < al.size(); i++) System.out.print(al.get(i) + ", "); System.out.println(); for(Object str : al) System.out.print(str + ", "); System.out.println(); Iterator it = al.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
1.1.2、LinkedList
LinkedList是基于链表的数据结构,在插入、修改、删除操作时效率较高,并且是非线程安全的。
public class Test { public static void main(String arg[]) { /** * LinkedList有两个构造方法 */ LinkedList linkedList1 = new LinkedList(); System.out.println("构造一个空列表 : " + linkedList1); linkedList1.add("linkedList1"); LinkedList linkedList2 = new LinkedList(linkedList1); System.out.println("构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列 : " + linkedList2); /** * LinkedList方法 */ linkedList1.add("linkedList1-1"); System.out.println("将指定元素添加到此列表的结尾 : " + linkedList1.get(1)); linkedList1.add(2, "linkedList1-2"); System.out.println("在此列表中指定的位置插入指定的元素 : " + linkedList1.get(2)); LinkedList linkedList = new LinkedList(); linkedList.add("linkedList"); linkedList2.addAll(linkedList); linkedList2.addAll(1, linkedList1); System.out.println("添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序 : " + linkedList2); linkedList.addFirst("linkedList-first"); System.out.println("将指定元素插入此列表的开头 : " + linkedList.get(0)); linkedList.addLast("linkedList-last"); System.out.println("将指定元素添加到此列表的结尾 : " + linkedList.get(linkedList.size() - 1)); linkedList.clear(); System.out.println("从此列表中移除所有元素 : " + linkedList.size()); linkedList.add("linkedList"); System.out.println("如果此列表包含指定元素,则返回 true : " + linkedList.contains("linkedList")); linkedList.add("linkedList-1"); linkedList.add("linkedList-2"); //Iterator<String> it = linkedList.descendingIterator(); System.out.println("获取但不移除此列表的头(第一个元素) : " + linkedList.element()); System.out.println("返回此列表中指定位置处的元素 : " + linkedList.get(0)); System.out.println("返回此列表的第一个元素 : " + linkedList.getFirst()); System.out.println("返回此列表的最后一个元素 : " + linkedList.getLast()); System.out.println("返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1 : " + linkedList.indexOf("linkedList-1")); System.out.println("返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1 : " + linkedList.lastIndexOf("lik")); ListIterator listIterator = linkedList.listIterator(); while (listIterator.hasNext()) System.out.println("返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始 : " + listIterator.next()); linkedList.offer("linkedList-offer"); System.out.println("将指定元素添加到此列表的末尾(最后一个元素): " + linkedList); //linkedList.offerFirst("linkedList-offer-first"); //linkedList.offerLast("linkedList-offer-last"); System.out.println("获取但不移除此列表的头(第一个元素): " + linkedList.peek()); //linkedList.peekFirst(); //linkedList.peekLast(); System.out.println(linkedList); System.out.println("获取并移除此列表的头(第一个元素): " + linkedList.poll()); //linkedList.pollFirst(); //linkedList.pollLast(); System.out.println(linkedList); //linkedList.pop(); //linkedList.push(); linkedList.remove(); System.out.println("获取并移除此列表的头(第一个元素): " + linkedList); //linkedList.remove(1); //linkedList.remove("linkList"); //linkedList.removeFirst(); //linkedList.removeLast(); //linkedList.removeFirstOccurrence("link"); //linkedList.removeLastOccurrence("link"); linkedList.set(1, "link"); System.out.println("返回此列表的元素数 : " + linkedList.size()); Object[] objArr = linkedList.toArray(); System.out.println("返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组 : " + objArr[1]); } }
LinkedList遍历
public class Test { public static void main(String arg[]) { LinkedList link = new LinkedList(); link.add("link1"); link.add("link2"); link.add("link3"); for(int i = 0; i < link.size(); i++) System.out.print(link.get(i) + ", "); System.out.println(); for(Object obj : link) System.out.print(obj + ", "); System.out.println(); Iterator it = link.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
1.1.3、Vector
Vector是一个动态数组,同ArrayList相似,只是Vector是线程安全的。
public class Test { public static void main(String arg[]) { /** * Vector有4个构造函数 */ Vector v1 = new Vector();//构造一个空向量,使其内部数据数组的大小为 10,其标准容量增量为零 v1.add("vector1-0"); Vector v2 = new Vector(v1);// 构造一个包含指定 collection 中的元素的向量,这些元素按其 collection 的迭代器返回元素的顺序排列 Vector v3 = new Vector(5);//使用指定的初始容量和等于零的容量增量构造一个空向量 Vector v4 = new Vector(5, 5);//使用指定的初始容量和容量增量构造一个空的向量 /** * Vector方法 */ v1.add("vector1-1"); System.out.println("将指定元素添加到此向量的末尾 : " + v1.get(1)); v1.add(2, "vector1-2"); System.out.println("在此向量的指定位置插入指定的元素 : " + v1.get(2)); v2.addAll(v1); System.out.println("将指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的顺序添加这些元素 : " + v2); Vector v5 = new Vector(); v5.add("vector5-1"); v2.add(1, v5); System.out.println("在指定位置将指定 Collection 中的所有元素插入到此向量中 : " + v2); v1.addElement("vector1-3"); System.out.println("将指定的组件添加到此向量的末尾,将其大小增加 1 : " + v1); System.out.println("返回此向量的当前容量 : " + v1.capacity()); //v1.clear();//从此向量中移除所有元素 System.out.println("如果此向量包含指定的元素,则返回 true : " + v1.contains("vector1-1")); System.out.println("如果此向量包含指定 Collection 中的所有元素,则返回 true : " + v2.containsAll(v4)); System.out.println("返回指定索引处的组件 : " + v1.elementAt(1)); Enumeration e = v1.elements(); while (e.hasMoreElements()) System.out.println("返回此向量的组件的枚举 : " + e.nextElement()); v1.ensureCapacity(5); System.out.println("增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数 : " + v1.size()); System.out.println("比较指定对象与此向量的相等性 : " + v1.equals(v1)); System.out.println("返回此向量的第一个组件(位于索引 0) 处的项): " + v1.firstElement()); System.out.println("返回向量中指定位置的元素 : " + v1.get(1)); System.out.println("返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回 -1 : " + v1.indexOf("vector1-1")); v1.insertElementAt("vector1-insert",2); System.out.println("将指定对象作为此向量中的组件插入到指定的 index 处 : " + v1); System.out.println("测试此向量是否不包含组件 : " + v1.isEmpty()); System.out.println("返回此向量的最后一个组件 : " + v1.lastElement()); System.out.println("返回此向量中最后一次出现的指定元素的索引;如果此向量不包含该元素,则返回 -1 : " + v1.lastIndexOf("vector")); System.out.println("返回此向量中最后一次出现的指定元素的索引,从 index 处逆向搜索,如果未找到该元素,则返回 -1 : " + v1.lastIndexOf("vector1-1", 3)); //v1.remove(1); //v1.remove("vector1-1"); //v1.removeAll(v1); //v1.removeElement("vector1-1"); //v1.removeElementAt(2); //v1.removeAllElements(); v2.retainAll(v1); System.out.println("在此向量中仅保留包含在指定 Collection 中的元素 : " + v2); System.out.println("返回此向量中的组件数 : " + v1.size()); List list = v1.subList(1, 2); for (Object obj : list) System.out.println("返回此 List 的部分视图,元素范围为从 fromIndex(包括)到 toIndex(不包括) : " + obj); Object[] objects = v1.toArray(); for(Object obj : objects) System.out.println("返回一个数组,包含此向量中以恰当顺序存放的所有元素 : " + obj); System.out.println("返回此向量的字符串表示形式,其中包含每个元素的 String 表示形式 : " + v1.toString()); } }
Vector遍历
public class Test { public static void main(String arg[]) { Vector v = new Vector(); v.add("vector1"); v.add("vector2"); v.add("vector3"); for(Object obj : v) System.out.print(obj + ", "); System.out.println(); for(int i = 0; i < v.size(); i++) System.out.print(v.get(i) + ", "); System.out.println(); Iterator it = v.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
ArrayList,LinkedList,Vestor区别及其优缺点
1.1.4、Stack
栈是Vector的一个子类,是一个标准的后进先出的栈,除了拥有vector的所有方法外,也定义了自己的一些方法。
public class Test { public static void main(String[] args) { Stack stack = new Stack(); System.out.println("测试堆栈是否为空 : " + stack.isEmpty()); System.out.println("把项压入堆栈顶部 : " + stack.push("stack1")); System.out.println("查看堆栈顶部的对象,但不从堆栈中移除它 : " + stack.peek()); System.out.println("移除堆栈顶部的对象,并作为此函数的值返回该对象 : " + stack.pop()); stack.push("stack1"); stack.push("stack2"); stack.push("stack3"); System.out.println("返回对象在堆栈中的位置,以 1 为基数 : " + stack.search("stack2")); } }
Stack遍历
public class Test { public static void main(String[] args) { Stack stack = new Stack(); stack.push("stack1"); stack.push("stack2"); stack.push("stack3"); for(Object obj : stack) System.out.print(obj + ", "); System.out.println(); for(int i = 0; i < stack.size(); i++ ) System.out.print(stack.get(i) + ", "); System.out.println(); Iterator it = stack.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
1.2、ArrayList、LinkedList、Vector、Stack对比
1.2.1、线程安全
Vector、Stack是线程安全的,ArrayList、LinkedList是非线程安全
1.2.2、实现方式
LinkedList是双向链表,ArrayList、Vector、Stack是数组
1.2.3、容量扩展
由于ArrayList和Vector、Stack使用数组实现,当数组长度不够时,其内部会创建一个更大的数组,然后将原数组中的数据拷贝至新数组中。
ArrayList如需扩展,则每次至少扩展至(原长度*3)/2 + 1(具体实现可看其的ensureCapacity方法)
Vector、Stack如果在创建Vector时不指定capacityIncrement(自动扩展长度)的值,如需扩展,则每次至少扩展至原长度的2倍(具体实现可看其的ensureCapacityHelper方法)
1.2.4、效率
查询:ArrayList直接通过下标进行定位,LinkedList则需要进行遍历,平均遍历次数应为n/4。对于指定位置查询,由于可以通过下标直接进行定位,ArrayList的速度远快于LinkedList,但是如果都为首尾位置的查询,情况会大为不同,因为LinkedList也是可以直接定位到首尾位置的,此时ArrayList和LinkedList的效率相同。
插入、修改:LinkedList效率高于ArrayList,ArrayList的插入需要考虑扩容和移动。
删除:删除指定位置数据同上,清除所有数据则一样,都需要遍历。
2、Set(元素无放入顺序,不可重复)
HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key,
Map的key和Set都有一个共同的特性就是集合的唯一性,TreeMap更是多了一个排序的功能。
2.1、Set实现
2.1.1、HashSet
public class Test { public static void main(String[] args) { /** * HashSet有4个构造方法 */ HashSet hs1 = new HashSet();//构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75 HashSet hs2 = new HashSet(1);//构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75) HashSet hs3 = new HashSet(1, 1);//构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子 hs1.add("HashSet"); HashSet hs4 = new HashSet(hs1);//构造一个包含指定 collection 中的元素的新 set System.out.println(hs4); /** * HashSet方法 */ hs1.add("HashSet"); hs1.add("HashSet1"); System.out.println("如果此 set 中尚未包含指定元素,则添加指定元素 : " + hs1); hs1.clear(); System.out.println("从此 set 中移除所有元素 : " + hs1); hs1.add("HashSet"); System.out.println("如果此 set 包含指定元素,则返回 true : " + hs1.contains("HashSet")); System.out.println("如果此 set 不包含任何元素,则返回 true : " + hs1.isEmpty()); Iterator it = hs1.iterator(); while (it.hasNext()) System.out.println("返回对此 set 中元素进行迭代的迭代器 : " + it.next()); hs1.remove("HashSet"); System.out.println("如果指定元素存在于此 set 中,则将其移除 : " + hs1); System.out.println("返回此 set 中的元素的数量(set 的容量): " + hs1.size()); } }
HashSet遍历
public class Test { public static void main(String[] args) { HashSet hs = new HashSet(); hs.add("HashSet1"); hs.add("HashSet2"); hs.add("HashSet3"); for(Object obj : hs) System.out.print(obj + ", "); System.out.println(); Iterator it = hs.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
2.1.2、TreeSet
public class Test { public static void main(String[] args) { /** * TreeSet有4个构造方法 */ TreeSet ts1 = new TreeSet();//构造一个新的空 set,该 set 根据其元素的自然顺序进行排序 ts1.add("TreeSet1-0"); TreeSet ts2 = new TreeSet(ts1);//构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序 TreeSet ts3 = new TreeSet(Collator.getInstance());//构造一个新的空 TreeSet,它根据指定比较器进行排序 TreeSet ts4 = new TreeSet(ts1);//构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet System.out.println(ts2); /** * TreeSet方法 */ ts1.add("TreeSet1-1"); System.out.println("将指定的元素添加到此 set(如果该元素尚未存在于 set 中) : " + ts1); ts2.addAll(ts1); System.out.println("将指定 collection 中的所有元素添加到此 set 中 : " + ts2); System.out.println("返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null : " + ts1.ceiling("TreeSet1-0")); ts1.clear(); System.out.println("移除此 set 中的所有元素 : " + ts1); ts1.add("TreeSet1-0"); ts1.add("TreeSet1-1"); System.out.println("返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null : " + ts1.comparator()); System.out.println("如果此 set 包含指定的元素,则返回 true : " + ts1.contains("TreeSet1-0")); Iterator it = ts1.descendingIterator(); while (it.hasNext()) System.out.println("返回在此 set 元素上按降序进行迭代的迭代器 : " + it.next()); System.out.println("返回此 set 中所包含元素的逆序视图 : " + ts1.descendingSet()); System.out.println("返回此 set 中当前第一个(最低)元素 : " + ts1.first()); System.out.println("返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null : " + ts1.floor("TreeSet1-2")); System.out.println("返回此 set 的部分视图,其元素严格小于 toElement : " + ts1.headSet("TreeSet1-1")); System.out.println("返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null : " + ts1.higher("TreeSet1-1")); System.out.println(" 如果此 set 不包含任何元素,则返回 true : " + ts1.isEmpty()); Iterator ite = ts1.iterator(); while (ite.hasNext()) System.out.println("返回在此 set 中的元素上按升序进行迭代的迭代器 : " + ite.next()); System.out.println("返回此 set 中当前最后一个(最高)元素 : " + ts1.last()); System.out.println("返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null : " + ts1.lower("TreeSet1-1")); ts1.pollFirst(); System.out.println("获取并移除第一个(最低)元素;如果此 set 为空,则返回 null : " + ts1); ts1.pollLast(); System.out.println("获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null : " + ts1); ts1.remove("TreeSet1-1"); System.out.println("将指定的元素从 set 中移除(如果该元素存在于此 set 中) : " + ts1); System.out.println("返回 set 中的元素数(set 的容量) : " + ts1.size()); ts1.remove("TreeSet1-0"); ts1.remove("TreeSet1-1"); ts1.remove("TreeSet1-2"); ts1.remove("TreeSet1-3"); System.out.println("返回此 set 的部分视图,其元素范围从 fromElement 到 toElement : " + ts1.subSet("TreeSet1-0", "TreeSet1-3")); } }
TreeSet遍历
public class Test { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add("TreeSet1"); ts.add("TreeSet2"); ts.add("TreeSet3"); for(Object obj : ts) System.out.print(obj + ", "); System.out.println(); Iterator it = ts.iterator(); while (it.hasNext()) System.out.print(it.next() + ", "); } }
2.2、HashSet、TreeSet对比(都是非线程安全的)
TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值
HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例
3、Map
3.1、HashMap
public class Test { public static void main(String arg[]) { /** * HashMap有4个构造函数 */ HashMap hm1 = new HashMap();//构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap HashMap hm2 = new HashMap(4);// 构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap HashMap hm3 = new HashMap(1, 4);// 构造一个带指定初始容量和加载因子的空 HashMap hm1.put("m1", "map1"); HashMap hm4 = new HashMap(hm1);//构造一个映射关系与指定 Map 相同的新 HashMap System.out.println(hm4); /** * HashMap方法 */ System.out.println("从此映射中移除所有映射关系 : " + hm1.size()); hm1.put("m1", "map1"); System.out.println("如果此映射包含对于指定键的映射关系,则返回 true : " + hm1.containsKey("m1")); System.out.println("如果此映射将一个或多个键映射到指定值,则返回 true : " + hm1.containsValue("map1")); hm1.put("m2", "map2"); for(Object obj : hm1.entrySet()) System.out.println("返回此映射所包含的映射关系的 Set 视图 : " + obj); System.out.println("返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null : " + hm1.get("m1")); System.out.println("如果此映射不包含键-值映射关系,则返回 true : " + hm1.isEmpty()); for(Object obj : hm1.keySet()) System.out.println("返回此映射中所包含的键的 Set 视图 : " + obj); HashMap hm = new HashMap(); hm.put("h1", "hm1"); hm4.putAll(hm); hm4.putAll(hm1); System.out.println("将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系 : " + hm4); hm1.remove("m1"); System.out.println("从此映射中移除指定键的映射关系(如果存在): " + hm1.size()); for(Object c : hm1.values()) System.out.println("返回此映射所包含的值的 Collection 视图 : " + c); } }
map遍历
public class Test { public static void main(String arg[]) { HashMap<String, String> hm = new HashMap(); hm.put("m1", "map1"); hm.put("m2", "map2"); hm.put("m3", "map3"); /** * 遍历key */ for (Object key : hm.keySet()) System.out.println(key); /** * 遍历value */ for (Object value : hm.values()) System.out.println(value); /** * 遍历map */ for (Object obj : hm.entrySet()) System.out.println(obj); /** * 遍历map,获取key、value */ for (Map.Entry entry : hm.entrySet()) System.out.println(entry.getKey() + " = " + entry.getValue()); /** * 遍历map */ Iterator<Map.Entry<String, String>> it = hm.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = it.next(); System.out.print(entry + "; "); System.out.println(entry.getKey() + ", " + entry.getValue() + "; "); } } }
3.2、TreeMap
3.3、HashTabel
3.4、Properties
Java:Map与HashMap,Hashtable,HashSet比较
二、List、Set、Map区别
List:元素有序,可重复。List接口有三个实现类:LinkedList,ArrayList,Vector 。ArrayList是非线程安全的,效率高;Vector是基于线程安全的,效率低。LinkedList底层基于链表实现,链表增删快,查找慢 。
Set:元素无序、不可重
Map:元素按key、value存储。Map接口有三个实现类:HashMap,HashTable,LinkeHashMap 。HashMap非线程安全,高效,支持null;HashTable线程安全,低效,不支持null。