程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java編程那些事兒80——集合框架簡述

Java編程那些事兒80——集合框架簡述

編輯:關於JAVA

9.6.3 集合框架簡述

在JDK API中專門設計了一組類,這組類的功能就是實現各種各樣方式的數據存儲,這樣一組專門用來存儲其它對象的類,一般被稱為對象容器類,簡稱容器類,這組類和接口的設計結構也被統稱為集合框架(Collection Framework)。

這組類和接口都包含在java.util包中。

為了使整個集合框架中的類便於使用,在設計集合框架時大量的使用接口,實際實現的功能類實現對應的接口,這樣可以保證各個集合類的使用方式保持統一。

在集合框架中,提供的存儲方式共有兩種:

1、按照索引值操作數據

在這種存儲方式中,為每個存儲的數據設定一個索引值,存儲在容器中的第一個元素索引值是0,第二個索引值是1,依次類推。在操作數據時按照索引值操作對應的數據,實現這種方式的集合類都實現java.util.Collection接口。

2、按照名稱操作數據

在這種存儲方式中,為每個存儲的數據設定一個名稱(任意非null的對象都可以作為名稱),以後按照該名稱操作該數據,要求名稱不能重復,每個名稱對應唯一的一個值。這種存儲數據的方式也稱作名稱-數值對,也就是名值對存儲。實現這種方式的幾個類都實現java.util.Map接口。

這裡“按照索引值操作數據”的存儲方式,又按照容器內部是否能夠存儲重復的元素,劃分成兩類:

1、允許存儲重復元素。

這種存儲方式中,所有的類都實現了java.util.List接口。

2、不允許存儲重復元素。

這種存儲方式中,所有的類都實現了java.util.Set接口。

這樣,集合框架中的類就分成了三大類:

1、List系列

該系列中的類按照索引值來操作數據,允許存放重復的元素。

2、Set系列

該系列中的類按照索引值來操作數據,不允許存放重復的元素。

3、Map系列

該系列中的類按照名稱來操作數據,名稱不允許重復,值可以重復,一個名稱對應一個唯一的值。

而在數據結構中,實現數據的存儲又可以使用不同的數據結構類型進行存儲,例如數組、鏈表、棧、隊列和樹等,則以上三類集合框架可以使用不同的數據結構類進行實現,使用每種數據結構則具備該中數據結構的特點。例如使用數組則訪問速度快,使用鏈表則便於動態插入和刪除等,這樣就造成了集合框架的復雜性。

另外,在將對象存儲到集合類中,為了加快存儲的速度,要求被存儲對象的類中必須覆蓋equals方法和hashCode方法。

對於這些集合類,下面按照以上三個系列的順序一一進行說明。

9.6.3.1 List系列

List系列的類均實現List接口,大部分的類都以List作為類名的後綴,也有部分該體系中的類命名比較特殊。

該系列中的類,比較常見的有ArrayList和LinkedList兩個。其中ArrayList是以數組為基礎實現的List,而LinkedList則是以鏈表為基礎實現的List,ArrayList擁有數組的優點,而LinkedList擁有鏈表的優點。

由於該體系中的類均實現List接口,所以在這些類的內部,相同的功能方法聲明是保持一致的,下面進行一一介紹:

a、add方法

boolean add(Object o)

該方法的作用是追加對象o到已有容器的末尾。

另外一個add方法:

void add(int index, Object element)

該方法的作用是將對象element插入到容器中索引值為index的位置,原來位於該位置的對象以及後續的內容將依次向後移動。

b、addAll方法

boolean addAll(Collection c)

該方法的作用是將容器對象c中的每個元素依次添加到當前容器的末尾。

另外一個addAll方法:

boolean addAll(int index, Collection c)

該方法的作用是將容器對象c中的第一個元素插入到當前容器中索引值為index的位置,第二個元素插入到當前容器中索引值為index+1的位置,依次類推。而當前容器中原來位於index以及index索引值以後的元素則依次向後移動。

c、get方法

Object get(int index)

該方法的作用是返回當前容器對象中索引值為index的元素的內容。

d、indexOf方法

int indexOf(Object o)

該方法的作用是查找當前容器中是否存在對象o,如果存在則返回該對象第一次出現位置的索引值,如果不存在則返回-1。

另外一個方法lastIndexOf則是從末尾向前查找,返回從末尾向前第一次出現位置的索引值,如果不存在則返回-1。

e、remove方法

Object remove(int index)

該方法的作用是刪除索引值為index的對象的內容,如果刪除成功則返回被刪除對象的內容。

另外一個remove方法:

boolean remove(Object o)

該方法的作用是刪除對象內容為o的元素,如果相同的對象有多個,則只刪除索引值小的對象。如果刪除成功則返回true,否則返回false。

無論使用哪一個remove方法,類內部都自動移動將被刪除位置後續的所有元素向前移動,保證索引值的連續性。

f、set方法

Object set(int index, Object element)

該方法的作用是修改索引值為index的內容,將原來的內容修改成對象element的內容。

g、size方法

int size()

該方法的作用是返回當前容器中已經存儲的有效元素的個數。

h、toArray方法

Object[] toArray()

該方法的作用是將當前容器中的元素按照順序轉換成一個Object數組。

下面是一個簡單的以ArrayList類為基礎實現的List系列中類基本使用的示例,代碼如下:

import java.util.*;

/**

* 以ArrayList類為基礎演示List系列類的基本使用

*/

public class ArrayListUse {

 public static void main(String[] args) {

  //容器對象的初始化

  List list = new ArrayList();

  //添加數據

  list.add("1");

  list.add("2");

  list.add("3");

  list.add("1");

  list.add("1");

  //插入數據

  list.add(1,"12");

  //修改數據

  list.set(2, "a");

  //刪除數據

  list.remove("1");

  //遍歷

  int size = list.size();  //獲得有效個數

  //循環有效索引值

  for(int i = 0;i < size;i++){

   System.out.println((String)list.get(i));

  }

 }

}

該程序的運行結果為:

12

a

3

1

1

在List系列中,還包含了Stack(棧)類和Vector(向量)類,Stack類除了實現List系列的功能以外,還實現了棧的結構,主要實現了出棧的pop方法和入棧的push方法。

而Vector類由於需要兼容老版本JDK中緣故,所以在實現的方法中需要提供老版本Vector類中對應的方法,這樣導致Vector類中相同或類似的功能方法一般是成對出現的。

9.6.3.2 Set系列

Set系列中的類都實現了Set接口,該系列中的類均以Set作為類名的後綴。該系列中的容器類,不允許存儲重復的元素。也就是當容器中已經存儲一個相同的元素時,無法實現添加一個完全相同的元素,也無法將已有的元素修改成和其它元素相同。

Set系列中類的這些特點,使得在某些特殊場合的使用比較適合。

該系列中常見的類有:

1、CopyOnWriteArraySet

以數組為基礎實現的Set類。

2、HashSet

以哈希表為基礎實現的Set類。

3、LinkedHashSet

以鏈表為基礎實現的Set類。

4、TreeSet

以樹為基礎實現的Set類。

以不同的數據結構類型實現的Set類,擁有不同數據結構帶來的特性,在實際使用時,根據邏輯的需要選擇合適的Set類進行使用。

Set系列中的類的方法和List系列中的類的方法要比List系列中少很多,例如不支持插入和修改,而且對於Set系列中元素的遍歷也需要轉換為專門的Iterator(迭代器)對象才可以進行遍歷,遍歷時順序和Set中存儲的順序會有所不同。

下面是以HashSet類為基礎實現的示例代碼,代碼如下:

import java.util.*;

/**

* 以HashSet為基礎演示Set系列類的基本使用

*/

public class HashSetUse {

 public static void main(String[] args) {

  //容器對象的初始化

  Set set = new HashSet();

  //添加元素

  set.add("1");

  set.add("2");

  set.add("3");

  set.add("1");

  set.add("1");

  //刪除數據

  //set.remove("1");

  //遍歷

  Iterator iterator = set.iterator();

  while(iterator.hasNext()){

   System.out.println((String)iterator.next());

  }

 }

}

該程序的運行結果為:

3

2

1

9.6.3.3 Map系列

Map系列中的類都實現了Map接口,該系列中的部分類以Map作為類名的後綴。該系列容器類存儲元素的方式和以上兩種完全不同。

Map提供了一種使用“名稱:值”這樣的名稱和數值對存儲數據的方法,在該存儲方式中,名稱不可以重復,而不同的名稱中可以存儲相同的數值。具體這種存儲的格式將在示例代碼中進行實現。

在這種存儲結構中,任何不為null的對象都可以作為一個名稱(key)來作為存儲的值(value)的標識,使用這種形式更利於存儲比較零散的數據,也方便數據的查找和獲得。Map類中存儲的數據沒有索引值,系統會以一定的形式索引存儲的名稱,從而提高讀取數據時的速度。

該系列中常見的類有:

1、HashMap

以Hash(哈希表)為基礎實現的Map類。

2、LinkedHashMap

以鏈表和Hash(哈希表)為基礎實現的Map類。

3、TreeMap

以樹為基礎實現的Map類。

和上面的結構類似,以不同的數據結構實現的Map類,擁有不同數據結構的特點,在實際的項目中使用時,根據需要選擇合適的即可。

該系列的類中常見的方法如下:

a、get方法

Object get(Object key)

該方法的作用是獲得當前容器中名稱為key的結構對應的值。

b、keySet方法

Set keySet()

該方法的作用是返回當前容器中所有的名稱,將所有的名稱以Set的形式返回。使用這個方法可以實現對於Map中所有元素的遍歷。

c、put方法

Object put(Object key, Object value)

該方法的作用是將值value以名稱key的形式存儲到容器中。

d、putAll方法

void putAll(Map t)

該方法的作用是將Map對象t中的所有數據按照原來的格式存儲到當前容器類中,相當於合並兩個Map容器對象。

e、remove方法

Object remove(Object key)

該方法的作用是刪除容器中名稱為key的值。

f、size方法

int size()

該方法的作用是返回當前日期中存儲的名稱:值數據的組數。

g、values方法

Collection values()

該方法的作用是返回當前容器所有的值組成的集合,以Collection對象的形式返回。

下面是一個簡單的示例,在該示例中演示Map系列類的基本使用,代碼如下:

import java.util.*;

/**

* 以HashMap為基礎演示Map系列中類的使用

*/

public class HashMapUse {

 public static void main(String[] args) {

  //容器對象的初始化

  Map map = new HashMap();

  //存儲數據

  map.put("蘋果", "2.5");

  map.put("桔子", "2.5");

  map.put("香蕉", "3");

  map.put("菠蘿", "2");

  //刪除元素

  map.remove("桔子");

  //修改元素的值

  map.put("菠蘿", "5");

  //獲得元素個數

  int size = map.size();

  System.out.println("個數是:" + size);

  //遍歷Map

  Set set = map.keySet();

  Iterator iterator = set.iterator();

  while(iterator.hasNext()){

   //獲得名稱

   String name = (String)iterator.next();

   //獲得數值

   String value = (String)map.get(name);

   //顯示到控制台

   System.out.println(name + ":" + value);

  }

 }

}

該程序的運行結果為:

個數是:3

香蕉:3

菠蘿:5

蘋果:2.5

9.6.3.4 使用示例

如前所述,集合框架中的類只是提供了一種數據存儲的方式,在實際使用時,可以根據邏輯的需要選擇合適的集合類進行使用。

下面以一個字符串計算的示例演示集合類的實際使用。

該程序的功能為計算一個數字字符串,例如”1+2*31-5”、”12*30/34-450”等,的計算結果,在該示例中支持四則運算,但是不支持括號。本示例中計算的字符串要求合法。

該程序實現的原理是:首先按照運算符作為間隔,將字符串差分為數字字符串和運算符字符串的序列,由於分拆出的字符串數量不固定,所以存儲到List系列的Vector容器中,然後按照運算符的優先級進行計算。

該程序的代碼如下:

import java.util.*;

/**

* 計算字符串的值

*/

public class CalcStr {

 public static void main(String[] args) {

  String s = "1+20*3/5";

  double d = calc(s);

  System.out.println(d);

 }

 /**

 * 計算字符串的值

 * @param s 需要計算的字符串

 * @return 計算結果

 */

 public static double calc(String s){

  //拆分字符串

  Vector v = split(s);

  //print(v); //測試代碼

  //計算字符串

  double d = calcVector(v);

  return d;

 }

 /**

 * 將字符串拆分為數字和運算符。

 * 例如:"1+23*4"則拆分為:"1"、"+"、"23"、"*"和"4"

 * @param s 需要拆分的字符串

 * @return 拆分以後的結果

 */

 private static Vector split(String s){

  Vector v = new Vector();

  String content = "";

  int len = s.length(); //字符串長度

  char c;

  for(int i = 0;i < len;i++){

   c = s.charAt(i);

   //判斷是否為運算符

   if(c == '+' ||

   c == '-' ||

   c == '*' ||

   c == '/'){

   //存儲數字

    v.add(content);

   //存儲運算符

   v.add("" + c);

   //清除已有字符串

   content = "";

   }else{

     content += c; //連接字符串

   }

  }

  v.add(content); //添加最後一個數字

  return v;

 }

 /**

 * 測試代碼,輸出拆分以後的結果

 * @param v 需要打印的Vector對象

 */

 private static void print(Vector v){

  int size = v.size();

  for(int i = 0;i < size;i++){

   System.out.println((String)v.get(i));

  }

 }

 /**

 * 計算Vector中的數據

 * @param v 存儲拆分後字符串的Vector

 * @return 計算結果

 */

 private static double calcVector(Vector v){

  int index1;

  int index2;

  //計算乘除

  while(true){

   index1 = v.indexOf("*"); //乘號索引值

   index2 = v.indexOf("/"); //除號索引值

   //無乘除符號

   if(index1 == - 1 && index2 == -1){

    break;  //結束循環

   }

   //如果有乘號

   if(index1 != -1){

    //沒有除號或乘號在前

    if(index2 == -1 || index1 < index2){

     String s1 = (String)v.get(index1 - 1); //第一個數字

     String opr = (String)v.get(index1); //運算符

     String s2 = (String)v.get(index1 + 1); //第二個數字

     //計算

     String answer = calc(s1,s2,opr);

     //計算以後的處理

     handle(answer,index1 - 1,v);

    }

   }

   //有除號

   if(index2 != -1){

   //沒有乘號或除號在前

    if(index1 == -1 || index2 < index1){

     String s1 = (String)v.get(index2 - 1); //第一個數字

     String opr = (String)v.get(index2); //運算符

     String s2 = (String)v.get(index2 + 1); //第二個數字

     //計算

     String answer = calc(s1,s2,opr);

     //計算以後的處理

     handle(answer,index2 - 1,v);

    }

   }

  }

  //計算加

  int index3 = v.indexOf("+");

  while(index3 != -1){ //有加號

   String s1 = (String)v.get(index3 - 1); //第一個數字

   String opr = (String)v.get(index3); //運算符

   String s2 = (String)v.get(index3 + 1); //第二個數字

   //計算

   String answer = calc(s1,s2,opr);

   //計算以後的處理

   handle(answer,index3 - 1,v);

   //獲得下一個加號的位置

   index3 = v.indexOf("+");

  }

  //計算減

  index3 = v.indexOf("-");

  while(index3 != -1){ //有加號

   String s1 = (String)v.get(index3 - 1); //第一個數字

   String opr = (String)v.get(index3); //運算符

   String s2 = (String)v.get(index3 + 1); //第二個數字

   //計算

   String answer = calc(s1,s2,opr);

   //計算以後的處理

   handle(answer,index3 - 1,v);

   //獲得下一個減號的位置

   index3 = v.indexOf("-");

  }

  //反饋結果

  String data = (String)v.get(0);

  return Double.parseDouble(data);

 }

 /**

 * 計算兩個字符串類型的值運算結果

 * @param number1 數字1

 * @param number2 數字2

 * @param opr 運算符

 * @return 運算結果

 */

 private static String calc(String number1,String number2,String opr){

  //將字符串轉換為數字

  double d1 = Double.parseDouble(number1);

  double d2 = Double.parseDouble(number2);

  //判斷運算符

  if(opr.equals("+")){

   return "" + (d1 + d2);

  }

  if(opr.equals("-")){

   return "" + (d1 - d2);

  }

  if(opr.equals("*")){

   return "" + (d1 * d2);

  }

  if(opr.equals("/")){

   return "" + (d1 / d2);

  }

  return "0";  //運算符錯誤時返回0

 }

 /**

 * 計算以後的處理

 * @param answer 計算結果

 * @param index 參與計算的三個字符串中第一個字符串的起始位置

 * @param v 存儲字符串的容器

 */

 private static void handle(String answer,int index,Vector v){

  //刪除計算過的字符串

  for(int i = 0;i < 3;i++){

   v.remove(index);

  }

  //將計算結果插入到index位置

  v.insertElementAt(answer, index);

 }

}

該程序的運行結果為:

13.0

9.7 總結

在本章中,主要介紹了java.lang包和java.util包中比較常見的類的使用,熟悉了JDK API的基本使用,掌握了文檔的查閱以及方法調用等一些基本的技能,為後續章節的學習打下堅實的基礎。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved