频道栏目
首页 > 程序开发 > 软件开发 > Java > 正文
Java数据结构与算法之集合
2014-06-12 11:17:54         来源:Java数据结构与算法之集合  
收藏   我要投稿

线性表、链表、哈希表是常用的数据结构,在进行Java开发时,SDK已经为我们提供了一系列相应的类来实现基本的数据结构。这些类均在java.util包中。

\

一、Collection接口

Collection是最基本的集合接口,一个Collection代表一组Object。一些Collection允许相同元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。 <喎"/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgICDL+dPQyrXP1kNvbGxlY3Rpb26907/atcTA4La8sdjQ68zhuanBvbj2serXvLXEubnU7Lqvyv2jus7ess7K/bXEubnU7Lqvyv3Tw9PatLS9qNK7uPa/1bXEQ29sbGVjdGlvbqOs09DSu7j2Q29sbGVjdGlvbrLOyv21xLm51Oy6r8r908PT2rS0vajSu7j20MK1xENvbGxlY3Rpb26jrNXiuPbQwrXEQ29sbGVjdGlvbtPrtKvI67XEQ29sbGVjdGlvbtPQz+DNrLXE1KrL2KGjuvPSu7j2ubnU7Lqvyv3UytDt08O7p7i01sbSu7j2Q29sbGVjdGlvbqGjPC9wPgo8cD4gICAgyOe6zrHpwPpDb2xsZWN0aW9u1tC1xMO/0ru49tSqy9ijv7K7wttDb2xsZWN0aW9utcTKtbzKwODQzcjnus6jrMv8trzWp7PW0ru49ml0ZXJhdG9yKCm1xLe9t6ijrLjDt723qLe1u9jSu7j2tfy0+sb3o6zKudPDuMO1/LT6xve8tL/J1vDSu7fDzspDb2xsZWN0aW9u1tDDv9K7uPbUqsvYoaO15NDNtcTTw7eoyOfPwqO6ICA8YnI+CqGhoaGhoaGhSXRlcmF0b3IgIGl0ICA9ICBjb2xsZWN0aW9uLml0ZXJhdG9yKCk7ICAvLyAgu/G1w9K7uPa1/LT6xvcgIDxicj4KoaGhoaGhoaF3aGlsZShpdC5oYXNOZXh0KCkpICB7ICA8YnI+CqGhoaGhoaGhoaGhoU9iamVjdCAgb2JqICA9ICBpdC5uZXh0KCk7ICAvLyAgtcO1vc/C0ru49tSqy9ggIDxicj4KoaGhoaGhoaF9ICA8YnI+CiAgICDTyUNvbGxlY3Rpb26907/axcnJ+rXEwb249r3Tv9rKx0xpc3S6zVNldKGjICA8YnI+CjwvcD4KPHA+PHN0cm9uZz4gCiAgILb+oaJMaXN0vdO/2jwvc3Ryb25nPjwvcD4KPHA+IAogICBMaXN0ysfT0NDytcRDb2xsZWN0aW9uo6zKudPDtMu907/axNy5u76ryLe1xL/Y1sbDv7j21KrL2LLlyOu1xM671sOho9PDu6fE3Lm7yrnTw8v30v2jqNSqy9jU2kxpc3TW0LXEzrvWw6OswOAmIzIwMjg0O9Payv3X6c/CseqjqcC0t8POykxpc3TW0LXE1KrL2KOs1eLA4CYjMjAyODQ709pKYXZhtcTK/dfpoaMgus3PwsPm0qrM4bW9tcRTZXSyu82so6xMaXN01MrQ7dPQz+DNrLXE1KrL2KGjCiAgPC9wPgo8cD4gCiAgILP9wcu+39PQQ29sbGVjdGlvbr3Tv9qx2LG4tcRpdGVyYXRvcigpt723qM3io6xMaXN0u7nM4bmp0ru49mxpc3RJdGVyYXRvcigpt723qKOst7W72NK7uPZMaXN0SXRlcmF0b3K907/ao6y6zbHq17y1xEl0ZXJhdG9yvdO/2s/gscijrExpc3RJdGVyYXRvcrbgwcvSu9CpYWRkKCnWrsDgtcS3vbeoo6zUytDtzO2806Osyb6z/aOsyei2qNSqy9ijrLu5xNzP8sewu/LP8rrzsenA+qGjICA8L3A+CjxwPiAKICDV4sDvwdC+2dK7uPbP8rrzz/LHsLHpwPq1xERFTU86PC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">public void listIterator(){ String[] books = { "Struts2", "J2EE" }; List bookList = new ArrayList(); for(int i = 0;i < books.length; i++) { bookList.add(books[i]); } ListIterator lit = bookList.listIterator(); System.out.println("=====下面开始正向迭代====="); while(lit.hasNext()) { System.out.println(lit.next()); lit.add("-----分隔符-----"); } System.out.println("=====下面开始反向迭代====="); while(lit.hasPrevious()) { System.out.println(lit.previous()); } } 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。

三、LinkedList类

LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
 注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
 List list = Collections.synchronizedList(new LinkedList(...));

四、ArrayList类

ArrayList实现了可变大小的数组。
它允许所有元素,包括null。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

五、Vector类

Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

六、Stack 类

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的push和pop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。Stack刚创建后是空栈。

七、Set接口

Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。
 很明显,Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。
 请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。

八、Map接口

请注意,Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map接口提供3种集合的视图,Map的内容可以被当作一组key集合,一组value集合,或者一组key-value映射。

九、Hashtable类

Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。
 添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
Hashtable通过initial capacity和load factor两个参数调整性能。通常缺省的load factor较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。
使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:
    Hashtable numbers = new Hashtable();
    numbers.put(“one”, new Integer(1));
    numbers.put(“two”, new Integer(2));
    numbers.put(“three”, new Integer(3));
 要取出一个数,比如2,用相应的key:
    Integer n = (Integer)numbers.get(“two”);
    System.out.println(“two = ” + n);
 由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。
 Hashtable是同步的。

十、HashMap类

HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null value和null key。但是将HashMap视为Collection时(values()方法可返回Collection),其迭代器操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。

十一、WeakHashMap类

WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。

十二、总结

如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
  如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
  要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
  尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程

点击复制链接 与好友分享!回本站首页
相关TAG标签 数据结构 算法
上一篇:struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值
下一篇:java7 新特性 总结版
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站