首頁 >Java >java教程 >什麼是Java中集合類別?集合類別結構圖文實例講解

什麼是Java中集合類別?集合類別結構圖文實例講解

伊谢尔伦
伊谢尔伦原創
2017-05-30 11:29:382894瀏覽

一、Java中集合

  Java中集合類別是Java程式設計中使用最頻繁、最方便的類別。集合類別作為容器類別可以儲存任何類型的數據,當然也可以結合泛型儲存指定的類型(不過泛型僅在編譯期間有效,運行時是會被擦除的)。集合類別中儲存的僅是物件的引用,並不儲存物件本身。集合類別的容量可以在運作期間進行動態擴展,也提供許多很方便的方法,如求集合的並集、交集等。

二、集合類別結構

#  Java中的集合包含多種資料結構,如鍊錶、佇列、哈希表等。從類別的繼承結構來說,可以分為兩大類,一類是繼承自Collection接口,這類集合包含List、Set和Queue等集合類別。另一類是繼承自Map接口,這主要包含了哈希表相關的集合類別。下面我們來看看這兩大類別的繼承結構圖:

1、List、Set和Queue

圖中的綠色的虛線代表實現,綠色實線代表介面之間的繼承,藍色實線代表類別之間的繼承。

   (1)List:我們用比較多的List包含ArrayList和LinkedList,這兩者的差異也很明顯,從名稱上就可以看出。 ArrayList的底層的透過陣列實現,所以其隨機存取的速度比較快,但是對於需要頻繁的增刪的情況,效率就比較低了。而對於LinkedList,底層透過鍊錶來實現,所以增刪操作比較容易完成,但是對於隨機存取的效率比較低。

我們先看下兩者的插入效率:

package com.paddx.test.collection;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListTest {
public static void main(String[] args) {
for(int i=;i<;i++){
}
long start = System.currentTimeMillis();
LinkedList<Integer> linkedList = new LinkedList<Integer>();
for(int i=;i<;i++){
linkedList.add(,i);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for(int i=;i<;i++){
arrayList.add(,i);
}
System.out.println(System.currentTimeMillis() - end);
}
}

下面是本機執行的結果:

23

1227

  可以看出,在這種情況下,LinkedList的插入效率遠高於ArrayList,當然這是一種比較極端的情況。我們再來比較一下兩者隨機存取的效率:

package com.paddx.test.collection;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
public class ListTest {
public static void main(String[] args) {
Random random = new Random();
for(int i=;i<;i++){
}
LinkedList<Integer> linkedList = new LinkedList<Integer>();
for(int i=;i<;i++){
linkedList.add(i);
}
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for(int i=;i<;i++){
arrayList.add(i);
}
long start = System.currentTimeMillis();
for(int i=;i<;i++){
int j = random.nextInt(i+);
int k = linkedList.get(j);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
for(int i=;i<;i++){
int j = random.nextInt(i+);
int k = arrayList.get(j);
}
System.out.println(System.currentTimeMillis() - end);
}
}

下面是我本機執行的結果:

5277

##6

  很明顯可以看出,ArrayList的隨機存取效率比LinkedList高出好幾個數量級。透過這兩段程式碼,我們應該能夠比較清楚的知道LinkedList和ArrayList的差異和適應的場景。至於Vector,它是ArrayList的線程安全版本,而Stack則對應堆疊資料結構,這兩者用的比較少,這裡就不舉例了。


  (2)Queue:一般可以直接使用LinkedList完成,從上述類別圖也可以看出,LinkedList繼承自Deque,所以LinkedList具有雙端佇列的功能。 PriorityQueue的特點是為每個元素提供一個優先權,優先順序高的元素會優先出佇列。


  (3)Set:Set與List的主要差異是Set是不允許元素重複的,而List則可以允許元素重複的。判斷元素的重複需要根據物件的hash方法和equals方法來決定。這也是我們通常要為集合中的元素類別重寫hashCode方法和equals方法的原因。我們還是透過一個範例來看Set和List的差別,以及hashcode方法和equals方法的作用:

package com.paddx.test.collection;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class SetTest {
public static void main(String[] args) {
Person p1 = new Person("lxp",10);
Person p2 = new Person("lxp",10);
Person p3 = new Person("lxp",20);
ArrayList<Person> list = new ArrayList<Person>();
list.add(p1);
System.out.println("---------");
list.add(p2);
System.out.println("---------");
list.add(p3);
System.out.println("List size=" + list.size());
System.out.println("----分割线-----");
Set<Person> set = new HashSet<Person>();
set.add(p1);
System.out.println("---------");
set.add(p2);
System.out.println("---------");
set.add(p3);
System.out.println("Set size="+set.size());
}
static class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
System.out.println("Call equals();name="+name);
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return name.equals(person.name);
}
@Override
public int hashCode() {
System.out.println("Call hashCode(),age="+age);
return age;
}
}
}

   上述程式碼的執行結果如下:


---------
---------
List size=3
----分割线-----
Call hashCode(),age=10
---------
Call hashCode(),age=10
Call equals();name=lxp
---------
Call hashCode(),age=20
Set size=2

  從結果看出,元素加入List的時候,不執行額外的操作,可以重複。而加入Set之前需要先執行hashCode方法,如果傳回的值在集合中已存在,要繼續執行equals方法,如果equals方法傳回的結果也為真,則證明該元素已經存在,會將新的元素覆寫老的元素,如果回傳hashCode值不同,則直接加入集合。這裡記住一點,對於集合中元素,hashCode值不同的元素一定不相等,但是不相等的元素,hashCode值可能相同。


  HashSet與LinkedHashSet的差異在於後者可以保證元素插入集合的元素順序與輸出順序一致。而TresSet的差別在於其排序是依照Comparator來進行排序的,預設會依照字元的自然順序升序排列。


  (4)Iterable:從這個圖中可以看到Collection類別繼承自Iterable,該介面的作用是提供元素遍歷的功能,也就是說所有的集合類別(除Map相關的類別)都提供元素遍歷的功能。 Iterable裡麵包含了Iterator的迭代器,其來源碼如下,大家如果熟悉迭代器模式的話,應該很容易理解。

public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}

2、Map:

#

Map类型的集合最大的优点在于其查找效率比较高,理想情况下可以实现O(1)的时间复杂度。Map中最常用的是HashMap,LinkedHashMap与HashMap的区别在于前者能够保证插入集合的元素顺序与输出顺序一致。这两者与TreeMap的区别在于TreeMap是根据键值进行排序的,当然其底层的实现也有本质的区别,如HashMap底层是一个哈希表,而TreeMap的底层数据结构是一棵树。我们现在看下TreeMap与LinkedHashMap的区别:

package com.paddx.test.collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class MapTest {
public static void main(String[] args) {
Map<String,String> treeMap = new TreeMap<String,String>();
Map<String,String> linkedMap = new LinkedHashMap<String, String>();
treeMap.put("b",null);
treeMap.put("c",null);
treeMap.put("a",null);
for (Iterator<String> iter = treeMap.keySet().iterator();iter.hasNext();){
System.out.println("TreeMap="+iter.next());
}
System.out.println("----------分割线---------");
linkedMap.put("b",null);
linkedMap.put("c",null);
linkedMap.put("a",null);
for (Iterator<String> iter = linkedMap.keySet().iterator();iter.hasNext();){
System.out.println("LinkedHashMap="+iter.next());
}
}
}

运行上述代码,执行结果如下:

TreeMap=a
TreeMap=b
TreeMap=c
----------分割线---------
LinkedHashMap=b
LinkedHashMap=c
LinkedHashMap=a

  从运行结果可以很明显的看出这TreeMap和LinkedHashMap的区别,前者是按字符串排序进行输出的,而后者是根据插入顺序进行输出的。细心的读者可以发现,HashMap与TreeMap的区别,与之前提到的HashSet与TreeSet的区别是一致的,在后续进行源码分析的时候,我们可以看到HashSet和TreeSet本质上分别是通过HashMap和TreeMap来实现的,所以它们的区别自然也是相同的。HashTable现在已经很少使用了,与HashMap的主要区别是HashTable是线程安全的,不过由于其效率比较低,所以通常使用HashMap,在多线程环境下,通常用CurrentHashMap来代替。

三、总结

  本文只是从整体上介绍了Java集合框架及其继承关系。除了上述类,集合还提供Collections和Arrays两个工具类,此外,集合中排序跟Comparable和Comparator紧密相关。

以上是什麼是Java中集合類別?集合類別結構圖文實例講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn