jdk的集合框架的主体结构:
接口 |
简述 |
实现 |
操作特性 |
成员要求 |
Set |
成员不能重复 |
HashSet |
外部无序地遍历成员。 |
成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
TreeSet |
外部有序地遍历成员;附加实现了SortedSet, 支持子集等要求顺序的操作 |
成员要求实现caparable接口,或者使用 Comparator构造TreeSet。成员一般为同一类型。 |
LinkedHashSet |
外部按成员的插入顺序遍历成员 |
成员与HashSet成员类似 |
List |
提供基于索引的对成员的随机访问 |
ArrayList |
提供快速的基于索引的成员访问,对尾部成员的增加和删除支持较好 |
成员可为任意Object子类的对象 |
LinkedList |
对列表中任何位置的成员的增加和删除支持较好,但对基于索引的成员访问支持性能较差 |
成员可为任意Object子类的对象 |
Map |
保存键值对成员,基于键找值操作,compareTo或compare方法对键排序 |
HashMap |
能满足用户对Map的通用需求 |
键成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
TreeMap |
支持对键有序地遍历,使用时建议先用HashMap增加和删除成员,最后从HashMap生成TreeMap;附加实现了SortedMap接口,支持子Map等要求顺序的操作 |
键成员要求实现caparable接口,或者使用Comparator构造TreeMap。键成员一般为同一类型。 |
LinkedHashMap |
保留键的插入顺序,用equals 方法检查键和值的相等性 |
成员可为任意Object子类的对象,但如果覆盖了equals方法,同时注意修改hashCode方法。 |
IdentityHashMap |
使用== 来检查键和值的相等性。 |
成员使用的是严格相等 |
WeakHashMap |
其行为依赖于垃圾回收线程,没有绝对理由则少用 |
|
Java Collections Framework成员主要包括两种类型,即:Collection和Map类型。 在Java中提供了Collection和Map接口。其中List和Set继承了Collection接口;同时用Vector、ArrayList、LinkedList三个类实现List接口,HashSet、TreeSet实现Set接口。直接有HashTable、HashMap、TreeMap实现Map接口。Collection----一组独立的元素,通常这些元素都服从某种规则。List必须保持元素特定的顺序,而Set不能有重复元素。 Map----一组成对的“键值对”对象,即其元素是成对的对象,最典型的应用就是数据字典,并且还有其它广泛的应用。另外,Map可以返回其所有键组成的Set和其所有值组成的Collection,或其键值对组成的Set,并且还可以像数组一样扩展多维Map,只要让Map中键值对的每个“值”是一个Map即可。Set(interface): 存入Set的每个元素必须是唯一的,因为Set不保存重复元素。加入Set的Object必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
首先还要说一下迭代器:迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
壹--Vector
Vector基于Array的List,性能也就不可能超越Array,并且Vector是“sychronized”的,这个也是Vector和ArrayList的唯一的区别。Vector
类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector
的大小可以根据需要增大或缩小,以适应创建 Vector
后进行添加或移除项的操作。
用法如下:
package com.zzn.test;
import java.util.Vector;
public class Iterator {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
//Vector的创建
//使用Vector的构造方法进行创建
Vector v = new Vector(4);
//向Vector中添加元素
//使用add方法直接添加元素
v.add("Test0");
v.add("Test1");
v.add("Test2");
v.add("Test3");
v.add("Test4");
//从Vector中删除元素
v.remove("Test0"); //删除指定内容的元素
v.remove(0); //按照索引号删除元素
//获得Vector中已有元素的个数
int size = v.size();
System.out.println("size:" + size);
//遍历Vector中的元素
for(int i = 0;i < v.size();i++){
System.out.println(v.get(i));
}
}
}
贰--ArrayList
ArrayList同Vector一样是一个基于Array的,但是不同的是ArrayList不是同步的。所以在性能上要比Vector优越一些,但是当运行到多线程环境中时,可需要自己在管理线程的同步问题。从其命名中可以看出它是一种类似数组的形式进行存储,因此它的随机访问速度极快,动态的增加和减少元素。
package com.zzn.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
/**
* 迭代ArrayList()的4种方法;
*/
public class ArrayListTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//方法1
Iterator it1 = list.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
//方法2(与方法一大同小异)
for(Iterator it2 = list.iterator();it2.hasNext();){
System.out.println(it2.next());
}
//方法3
for(String tmp:list){
System.out.println(tmp);
}
//方法4
for(int i = 0;i < list.size(); i ++){
System.out.println(list.get(i));
}
}
}
叁--LinkedList:
LinkedList不同于前面两种List,它不是基于Array的,所以不受Array性能的限制。它每一个节点(Node)都包含两方面的内容:1.节点本身的数据(data);2.下一个节点的信息(nextNode)。所以
当对LinkedList做添加,删除动作的时候就不用像基于Array的List一样,必须进行大量的数据移动。只要更改nextNode的相关信息就可以实现了所以它适合于进行频繁进行插入和删除操作。它具有方法addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),这些方法(没有在任何接口或基类中定义过)使得LinkedList可以当作堆栈、队列和双向队列使用。这就是
LinkedList的优势。Iterator只能对容器进行向前遍历,而 ListIterator则继承了Iterator的思想,并提供了对List进行双向遍历的方法。
package com.zzn.test;
import java.util.Iterator;
import java.util.LinkedList;
/** *//**
* 迭代ArrayList()的4种方法;
*/
public class LinkedListTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add("B");
linkedList.add("C");
linkedList.add("D");
linkedList.add("E");
linkedList.add("F");
linkedList.addLast("Z");
linkedList.addFirst("A");
linkedList.add(1, "A2");
System.out.println("Original contents of ll: " + linkedList);
linkedList.remove("F");
linkedList.remove(2);
System.out.println("Contents of ll after deletion: " + linkedList);
linkedList.removeFirst();
linkedList.removeLast();
System.out.println("ll after deleting first and last: " + linkedList);
String val = (String)linkedList.get(2);//第几个位置
linkedList.set(2, val + "—Changed");
System.out.println("ll after change: " + linkedList);
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
肆--HashTable
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
package com.zzn.test;
import java.util.Hashtable;
public class HastTableTest {
public static void main(String[] args) {
Hashtable<String, Integer> numbers = new Hashtable<String, Integer>();
numbers.put("one", 1);
numbers.put("two", 2);
numbers.put("three", 3);
Integer n = numbers.get("two");
if (n != null) {
System.out.println("two = " + n);
}
}
}
伍--HashMap
HashMap把各个Object映射起来,实现了“键--值”对应的快速存取。注意,次实现是不同步的。
package com.zzn.test;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class HashMapTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
HashMap<String , String> myMap = new HashMap<String , String>();
myMap.put("hello", "你好");
myMap.put("bye", "再见");
myMap.put("thanks", "谢谢");
myMap.put("ok", "好的");
System.out.println("--------------------遍历key和value----------------------");
for (Iterator iter = myMap.entrySet().iterator();iter.hasNext();){
Map.Entry element = (Map.Entry)iter.next();
Object strKey = element.getKey();
Object strObj = element.getValue();
System.out.println("myMap.get(\""+strKey+"\")="+strObj);
}
System.out.println();
System.out.println("--------------------遍历整个HashMap----------------------");
Collection objs = myMap.entrySet();
for (Iterator iterator=objs.iterator(); iterator.hasNext();){
Object obj = iterator.next();
System.out.println(obj);
}
System.out.println();
System.out.println("--------------------遍历HashMap的key----------------------");
Collection keys = myMap.keySet();
for (Iterator iterator=keys.iterator(); iterator.hasNext();){
Object key = iterator.next();
System.out.println(key);
}
System.out.println();
System.out.println("--------------------遍历HashMap的value----------------------");
Collection values = myMap.values();
for (Iterator iterator=values.iterator(); iterator.hasNext();){
Object value = iterator.next();
System.out.println(value);
}
}
}
陆--TreeMap
package com.zzn.test;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
public class TreeMapTest {
public static void main(String[] args) {
TreeMap tm = new TreeMap();
for (int i = 0; i < 10; i++) {
String a = "key" + i;
String b = "value" + i;
tm.put(a, b);
}
// 第一种方法
// 使用entrySet()方法生成一个由Map.entry对象组成的Set,
// 而Map.entry对象包括了每个元素的"键"和"值".这样就可以用iterator了
Iterator it = tm.entrySet().iterator();
while (it.hasNext()) {
// entry的输出结果如key0=value0等
Map.Entry entry =(Map.Entry) it.next();
Object key = entry.getKey();
Object value=entry.getValue();
System.out.println(entry);
System.out.println(key);
System.out.println(value);
}
//第二种方法
//这是用TreeMap的keySet()方法,生成的对象是由key对象组成的Set
//再利用TreeMap的get(key)方法,得到对应的value值
Iterator ite = tm.keySet().iterator();
while (ite.hasNext()) {
//it.next()得到的是key,tm.get(key)得到obj
System.out.println(tm.get(ite.next()));
}
}
}
柒--LindedHashMap
LinkedHashMap扩展HashMap,以插入顺序将关键字/值对添加进链接哈希映像中。象LinkedHashSet一样,LinkedHashMap内部也采用双重链接式列表。
package com.zzn.test;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
public class LinkedHashMapTest {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
LinkedHashMap lHashMap = new LinkedHashMap();
lHashMap.put("One", new Integer(1));
lHashMap.put("Two", new Integer(2));
lHashMap.put("three", new Integer(3));
lHashMap.put("four", new Integer(4));
System.out.println("~~~~~~~~~~~~~~~~~~方法一:迭代LinkedHashMap类型的lHashMap;~~~~~~~~~~~~~~~~~~~~");
for(Iterator it=lHashMap.values().iterator();it.hasNext();){
System.out.println(it.next());
}
System.out.println("~~~~~~~~~~~~~~~~~~方法二:迭代LinkedHashMap类型的lHashMap;~~~~~~~~~~~~~~~~~~~~");
Collection c = lHashMap.values();
Iterator iter = c.iterator();
while (iter.hasNext()){
System.out.println(iter.next());
}
System.out.println("~~~~~~~~~~~~~~~~~~Get Set view of Keys from Java LinkedHashMap;~~~~~~~~~~~~~~~~~~~~");
Iterator itr = lHashMap.keySet().iterator();
while (itr.hasNext()){
System.out.println(itr.next());
}
//key - 要测试其是否在此映射中存在的键
boolean blnExistKey = lHashMap.containsKey("Two");
System.out.println(blnExistKey);
//value - 要测试其是否在此映射中存在的值
boolean blnExistValue = lHashMap.containsValue("1");
System.out.println(blnExistValue);
System.out.println("~~~~~~~~~~~~~~~~~~从LinkedHashMap中移除key为“Two”的值;~~~~~~~~~~~~~~~~~~~~");
Object obj = lHashMap.remove("Two");//从LinkedHashMap中移除key为“Two”的值;
System.out.println(obj+ " Removed from LinkedHashMap"); //输出移除的值;
}
}
捌--HashSet
此类实现 Set 接口,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size;次实现是不同步的;为快速查找而设计的Set。存入HashSet的对象必须定义hashCode();
package com.zzn.test;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetTest {
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
HashSet hashSet=new HashSet();
String a=new String("A");
String b=new String("B");
String c=new String("B");
String d="D";
hashSet.add(a);
hashSet.add(b);
hashSet.add(d);
System.out.println("~~~~~~~~~~~b和c得值相同;所以size()是3~~~~~~~~~~~");
System.out.println(hashSet.size());
String cz=hashSet.add(c)?"此对象不存在":"已经存在";
System.out.println("测试是否可以添加对象 "+cz);
System.out.println("~~~~~~~~~~~测试是否为空;~~~~~~~~~~~");
System.out.println(hashSet.isEmpty());
System.out.println("~~~~~~~~~~~测试其中是否已经包含某个对象;~~~~~~~~~~~");
System.out.println(hashSet.contains("A"));
System.out.println("~~~~~~~~~~~迭代;~~~~~~~~~~~");
Iterator ir=hashSet.iterator();
while(ir.hasNext())
{
System.out.println(ir.next());
}
System.out.println("~~~~~~~~~~~测试某个对象是否可以删除;~~~~~~~~~~~");
System.out.println(hashSet.remove("a"));
System.out.println(hashSet.remove("A"));
System.out.println("~~~~~~~~~~~经过测试,如果你想再次使用ir变量,必须重新更新以下;~~~~~~~~~~~");
ir=hashSet.iterator();
while(ir.hasNext())
{
System.out.println(ir.next());
}
}
}
玖--LindedHashSet
具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
package com.zzn.test;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkedHashSetTest {
public static void main(String[] args) {
LinkedHashSet<Integer> lhashSet = new LinkedHashSet<Integer>();
lhashSet.add(new Integer("1"));
lhashSet.add(new Integer("2"));
lhashSet.add(new Integer("3"));
System.out.println("~~~~~~~~~~~~~~~把LinkedHashSet的所有元素复制到 Object Array中~~~~~~~~~~~~~~~");
Object[] objArray = lhashSet.toArray();
for (Object inte: objArray){
System.out.println(inte);
}
System.out.println("~~~~~~~~~~~~~~~检查lhashSet中是否存在值为3的元素~~~~~~~~~~~~~~~");
boolean bool = lhashSet.contains(new Integer("3"));
System.out.println(bool);
System.out.println("~~~~~~~~~~~~~~~迭代lhashSet~~~~~~~~~~~~~~~");
for(Iterator it =lhashSet.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
拾--TreeSet
TreeSet: 保持次序的Set,底层为树结构。使用它可以从Set中提取有序的序列,TreeSet为使用树来进行存储的Set接口提供了一个工具,对象按升序存储.访问和检索是很快的。在存储了大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择。
package com.zzn.test;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetTest {
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
System.out.println("~~~~~~~~~~~~~~TreeSet的排序功能~~~~~~~~~~~~~~~");
TreeSet ts = new TreeSet();
ts.add("B");
ts.add("C");
ts.add("A");
ts.add("E");
ts.add("F");
ts.add("D");
//注意如果TreeSet中有重复(一样的)值,TreeSet会把其他相同的排除掉;
ts.add("A");
System.out.println(ts);
System.out.println("~~~~~~~~~~~~~~TreeSet的迭代~~~~~~~~~~~~~~~");
for(Iterator it =ts.iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
下面说一下他们之间的区别
一、Hashtable和HashMap的区别:
①都属于Map接口的类,实现了将惟一键映射到特定的值上。Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
②Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机
制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:Map Collections.synchronizedMap(Map m)这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层
的HashMap即使是在多线程的环境中也是安全的。
③HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。
④HashMap被优先选择。
二、ArrayList和LinkedList
① ArrayList其实是包装了一个数组 Object[],当实例化一个ArrayList时,一个数组也被实例化,当向ArrayList中添加对象是,数组的大小也相应的改变。这样就带来以下有缺点:
快速随即访问 你可以随即访问每个元素而不用考虑性能问题,通过调用get(i)方法来访问下标为i的数组元素。
向其中添加对象速度慢 当你创建数组是并不能确定其容量,所以当改变这个数组时就必须在内存中做很多事情。
操作其中对象的速度慢 当你要想数组中任意两个元素中间添加对象时,数组需要移动所有后面的对象。
②LinkedList是通过节点直接彼此连接来实现的。每一个节点都包含前一个节点的引用,后一个节点的引用和节点存储的值。当一个新节点插入时,只需要修改其中保持先后关系的节点的引用即可,
当删除记录时也一样。这样就带来以下有缺点:
操作其中对象的速度快 只需要改变连接,新的节点可以在内存中的任何地方
不能随即访问 虽然存在get()方法,但是这个方法是通过遍历接点来定位的所以速度慢。
③当一些被定义好的数据需要放到与数组对应的List中,ArrayList是很好的选择,因为它可以动态变化,但是不要在整个应用程序用频繁的使用。当你要很方便的操作其中的数据而不用随即访问时
LinkList是很好的选择。如果你要频繁随即访问建议使用数组。