Java開發中的容器概念、分類與用法深入詳解

Java開發中的容器概念、分類與用法深入詳解

本文例項講述了Java開發中的容器概念、分類與用法。分享給大家供大家參考,具體如下:

1、容器的概念

在Java當中,如果有一個類專門用來存放其它類的物件,這個類就叫做容器,或者就叫做集合,集合就是將若干性質相同或相近的類物件組合在一起而形成的一個整體

2、容器與陣列的關係

之所以需要容器:

① 陣列的長度難以擴充
② 陣列中資料的型別必須相同

容器與陣列的區別與聯絡:

① 容器不是陣列,不能通過下標的方式訪問容器中的元素
② 陣列的所有功能通過Arraylist容器都可以實現,只是實現的方式不同
③ 如果非要將容器當做一個陣列來使用,通過toArraylist方法返回的就是一個陣列

示例程式:


package IT;
import java.util.ArrayList;
import java.util.Iterator;
//陣列的所有功能通過ArrayList容器都可以實現,只是實現的方式不同
public class App
{
  public static void main(String[] args)
  {
   ArrayList<Integer> arrayList = new ArrayList<Integer>();
   arrayList.add(12);
   arrayList.add(10);
   arrayList.add(35);
   arrayList.add(100);
   Iterator<Integer> iterator = arrayList.iterator();//獲取容器的迭代器
   while(iterator.hasNext())
   {
    Integer value = iterator.next();//獲取當前遊標右邊的元素,同時遊標右移-->
    System.out.println(value);
   }
   System.out.println("通過ArrayList容器獲取一個陣列arr:");
   Object[] arr = arrayList.toArray();
   for(int i=0;i<arr.length;i  )
   {
    System.out.println(arr[i]);
   }
  }
}

輸出結果:


12
10
35
100

通過ArrayList容器獲取一個陣列arr:


12
10
35
100

3、容器常用的幾個方法

boolean add(Object obj):向容器中新增指定的元素
Iterator iterator():返回能夠遍歷當前集合中所有元素的迭代器
Object[] toArray():返回包含此容器中所有元素的陣列。
Object get(int index):獲取下標為index的那個元素
Object remove(int index):刪除下標為index的那個元素
Object set(int index,Object element):將下標為index的那個元素置為element
Object add(int index,Object element):在下標為index的位置新增一個物件element
Object put(Object key,Object value):向容器中新增指定的元素
Object get(Object key):獲取關鍵字為key的那個物件
int size():返回容器中的元素數

例項程式:


package IT;
import java.util.ArrayList;
public class App
{
  public static void main(String[] args)
  {
   ArrayList<Integer> arrayList = new ArrayList<Integer>();
   arrayList.add(12);
   arrayList.add(10);
   arrayList.add(35);
   arrayList.add(100);
   System.out.println("原容器中的元素為:");
   System.out.println(arrayList);
   System.out.println("\n");
   /*******重置set(int index,Object element)*******/
   System.out.println("將下標為1位置的元素置為20,將下標為2位置的元素置為70");
   arrayList.set(1, 20);
   arrayList.set(2, 70);
   System.out.println("重置之後容器中的元素為:");
   System.out.println(arrayList);
   System.out.println("\n");
   /*******中間插隊add(int index,Object element)*******/
   System.out.println("在下標為1的位置插入一個元素,-----插入元素:此時容器後面的元素整體向後移動");
   arrayList.add(1, 80);//在下標為1的位置插入一個元素,此時容量加1,-----位置後面的元素整體向後移動
   System.out.println("插入之後容器中的元素為:");
   System.out.println(arrayList);
   System.out.println("插入之後容器中的容量為:");
   System.out.println(arrayList.size());
   System.out.println("\n");
   /*******中間刪除元素remove(int index)*******/
   System.out.println("將下標為3位置的元素70刪除,-----刪除元素:此時容器位置後面的元素整體向前移");
   arrayList.remove(3);
   System.out.println("刪除之後容器中的元素為:");
   System.out.println(arrayList);
   System.out.println("刪除之後容器中的容量為:");
   System.out.println(arrayList.size());
  }
}

執行結果:


原容器中的元素為:
[12, 10, 35, 100]
將下標為1位置的元素置為20,將下標為2位置的元素置為70
重置之後容器中的元素為:
[12, 20, 70, 100]
在下標為1的位置插入一個元素,-----插入元素:此時容器後面的元素整體向後移動
插入之後容器中的元素為:
[12, 80, 20, 70, 100]
插入之後容器中的容量為:
5
將下標為3位置的元素70刪除,-----刪除元素:此時容器位置後面的元素整體向前移
刪除之後容器中的元素為:
[12, 80, 20, 100]
刪除之後容器中的容量為:
4

4、容器的分類

容器分為Set集、List列表、Map對映

Set集合:由於內部儲存結構的特點,Set集合中不區分元素的順序,不允許出現重複的元素,TreeSet容器特殊,元素放進去的時候自然而然就有順序了,Set容器可以與數學中的集合相對應:相同的元素不會被加入

List列表:由於內部儲存結構的特點,List集合中區分元素的順序,且允許包含重複的元素。List集合中的元素都對應一個整數型的序號記載其在容器中的位置,可以根據序號存取容器中的元素—有序,可以重複

Map對映:由於內部儲存結構的特點,對映中不能包含重複的鍵值,每個鍵最多隻能對映一個值,否則會出現覆蓋的情況(後面的value值會將前面的value值覆蓋掉),Map是一種把鍵物件和值物件進行對映的集合,即Map容器中既要存放資料本身,也要存放關鍵字:相同的元素會被覆蓋

注意:對於Set和Map來說,元素放進去之後是沒有順序的,如果希望元素放進去之後是有順序的,可以用treeSet和treeMap儲存資料。

例項程式:


var set2 = mutable.Set.empty[Int]
set2  = 10
set2   = List(50,100,200)
set2  = 500
println("Set輸出的結果:")
println(set2)
var map3 = mutable.Map.empty[String,Double]
map3  = "Spark"->90.0
map3  = "Hadoop"->80.0
map3   = List("Scala"->100.0,"Java"->60.0)
println("Map輸出的結果:")
println(map3)

執行結果:


Set輸出的結果:
Set(100, 50, 500, 10, 200)
Map輸出的結果:
Map(Hadoop -> 80.0, Spark -> 90.0, Scala -> 100.0, Java -> 60.0)

例項程式:


var treeSet = TreeSet(10,20,30,90,100,200,50)
println(treeSet)
/*鍵值對排序是根據key的值進行排序的,沒有value的事情,讓我聯想到了MapReduce中排序的時候之所以根據k2
而不是v2的值進行排序,這是因為雜湊對映內部決定的,而不是MapReduce決定的
呵呵!注意:排序區分大小寫的哦!!!*/
var treeSet2 = TreeSet[String]("Spark","Anang","Baby","Hello")
println(treeSet2)
var treeMap = TreeMap[String,Integer]("Java"->100,"Scala"->88,"Python"->60,"Anglebaby"->500)
println(treeMap)

執行結果:


TreeSet(10, 20, 30, 50, 90, 100, 200)
TreeSet(Anang, Baby, Hello, Spark)
Map(Anglebaby -> 500, Java -> 100, Python -> 60, Scala -> 88)

5、toString()方法的使用:凡是把類物件放到容器中,相應的類都應該實現Object類中的toString()方法;凡是Java中自帶的資料型別,都已經重寫完了toString()方法

例項1:(未重寫toString()方法之前)


package IT;
public class App
{
  public static void main(String[] args)
  {
   //Java中自帶的類
   System.out.println("-----凡是Java中自帶的資料型別都已經重寫完了toString()方法!---");
   System.out.println(new Integer(2).toString());
   System.out.println(new String("zhang").toString());
   //使用者自定義的類Student
   System.out.println(new Student("zhangsan",99.8).toString());
  }
}
class Student
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
}

輸出結果:


-----凡是Java中自帶的資料型別都已經重寫完了toString()方法!---
2
zhang
[email protected]

例項2:(重寫完toString()方法之後)


package IT;
import java.util.ArrayList;
public class App
{
  public static void main(String[] args)
  {
   ArrayList<Student> arr = new ArrayList<Student>();
   arr.add(new Student("zhangsan",89.8));
   arr.add(new Student("lisi",90));
   arr.add(new Student("wangwu",60.6));
   System.out.println(arr);
  }
}
class Student
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
}

輸出結果:


[zhangsan 89.8, lisi 90.0, wangwu 60.6]

6、Comparable介面中的compareTo()方法:凡是需要進行比較排序的類都應該實現Comparable介面中的compareTo()方法;凡是把類物件放到以樹為內部結構的容器中都應該實現Comparable介面中的compareTo()方法

例項1:


package IT;
import java.util.ArrayList;
import java.util.Collections;
public class App
{
  public static void main(String[] args)
  {
   ArrayList<Student> arr = new ArrayList<Student>();
   arr.add(new Student("zhangsan",89.8));
   arr.add(new Student("lisi",90));
   arr.add(new Student("wangwu",60.6));
   arr.add(new Student("wangting",85.6));
   Collections.sort(arr);
   for (Student student : arr)
  {
   System.out.println(student);
  }
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   return (int) (this.score - obj.score);//比較的標準為score進行升序
 }
}

輸出結果:


wangwu 60.6
wangting 85.6
zhangsan 89.8
lisi 90.0

例項2:


package IT;
import java.util.TreeSet;
public class App
{
  public static void main(String[] args)
  {
   TreeSet<Student> treeSet = new TreeSet<Student>();
   treeSet.add(new Student("wangwu",60.6));
   treeSet.add(new Student("lisi",90.0));
   treeSet.add(new Student("wangting",85.6));
   treeSet.add(new Student("zhangsan",60.6));
   for (Student student : treeSet)
   {
    System.out.println(student);
   }
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   if(this.score > obj.score)
    return 1;
   else
    return -1;
 }
}

輸出結果:


zhangsan 60.6
wangwu 60.6
wangting 85.6
lisi 90.0

7、凡是把類物件放到以雜湊表為內部儲存結構的容器中,相應的類必須要實現equals方法和hashCode方法,這樣才符合雜湊表真實的邏輯功能.

例項程式1:(為重寫之前)


package IT;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class App
{
  public static void main(String[] args)
  {
   //Java中自帶的資料型別
   System.out.println("先測試Java中自帶的資料型別:");
   HashMap<String, Double> hashMap1 = new HashMap<String,Double>();
   hashMap1.put("zhangsan", 96.0);
   hashMap1.put("lisi", 88.6);
   hashMap1.put("wangwu", 98.6);
   hashMap1.put("wangting", 87.5);
   hashMap1.put("zhangsan", 96.0);
   hashMap1.put("lisi", 88.6);
   hashMap1.put("wangwu", 98.6);
   hashMap1.put("wangting", 87.5);
   Set<String> keySet = hashMap1.keySet();
   Iterator<String> iterator = keySet.iterator();
   while(iterator.hasNext())
   {
    String key = iterator.next();
    System.out.println(key "\t" hashMap1.get(key));
   }
   System.out.println("Java中自帶的資料型別:相同的物件會覆蓋!");
   System.out.println("\n");
   //使用者自定義的資料型別:為重寫之前
   System.out.println("測試使用者自定義的資料型別--未重寫兩個方法之前:");
   HashMap<Student, String> hashMap2 = new HashMap<Student,String>();
   hashMap2.put(new Student("zhangsan",88.8), "beijing");
   hashMap2.put(new Student("lisi",88.8), "beijing");
   hashMap2.put(new Student("wangwu",66.9), "beijing");
   hashMap2.put(new Student("zhangsan",88.8), "beijing");
   hashMap2.put(new Student("lisi",88.8), "beijing");
   hashMap2.put(new Student("wangwu",66.9), "beijing");
   Set<Student> keySet2 = hashMap2.keySet();
   Iterator<Student> iterator2 = keySet2.iterator();
   while(iterator2.hasNext())
   {
    Student key = iterator2.next();
    System.out.println(key "\t" hashMap2.get(key));
   }
   System.out.println("如果沒有重寫:導致相同的物件不會被覆蓋!");
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   if(this.score > obj.score)
    return 1;
   else
    return -1;
 }
}

輸出結果:


先測試Java中自帶的資料型別:
wangting 87.5
wangwu 98.6
lisi 88.6
zhangsan 96.0
Java中自帶的資料型別:相同的物件會覆蓋!
測試使用者自定義的資料型別--為重寫兩個方法之前:
zhangsan 88.8 beijing
wangwu 66.9 beijing
lisi 88.8 beijing
wangwu 66.9 beijing
zhangsan 88.8 beijing
lisi 88.8 beijing
如果沒有重寫:導致相同的物件不會被覆蓋!

例項程式2:重寫之後


package IT;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class App
{
  public static void main(String[] args)
  {
   //使用者自定義的資料型別:為重寫之後
   System.out.println("測試使用者自定義的資料型別--重寫兩個方法之後:");
   HashMap<Student, String> hashMap2 = new HashMap<Student,String>();
   hashMap2.put(new Student("zhangsan",88.8), "beijing");
   hashMap2.put(new Student("lisi",88.8), "beijing");
   hashMap2.put(new Student("wangwu",66.9), "beijing");
   hashMap2.put(new Student("zhangsan",88.8), "beijing");
   hashMap2.put(new Student("lisi",88.8), "beijing");
   hashMap2.put(new Student("wangwu",66.9), "beijing");
   Set<Student> keySet2 = hashMap2.keySet();
   Iterator<Student> iterator2 = keySet2.iterator();
   while(iterator2.hasNext())
   {
    Student key = iterator2.next();
    System.out.println(key "\t" hashMap2.get(key));
   }
   System.out.println("重寫過後:相同的物件會被覆蓋!");
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   if(this.score > obj.score)
    return 1;
   else
    return -1;
 }
 @Override
 public int hashCode()
 {
  return (int) (this.name.hashCode()*score);//保證相同物件對映到同一個索引位置
 }
 @Override
 public boolean equals(Object obj)
 {
  Student cc = (Student)obj;
  return this.name==cc.name&&this.score==cc.score;
 }
}

輸出結果:


測試使用者自定義的資料型別--重寫兩個方法之後:
wangwu 66.9 beijing
zhangsan 88.8 beijing
lisi 88.8 beijing
重寫過後:相同的物件會被覆蓋!

8、重要的一個邏輯:邏輯上來講,只要兩個物件的內容相同,其地址(hashCode()返回值)以及這兩個物件就應該相同(equals()),

例項程式(為重寫之前):


package IT;
public class App
{
  public static void main(String[] args)
  {
   //Java中自帶的資料型別
   System.out.println(new Integer(1).equals(new Integer(1)));
   System.out.println(new Integer(1).hashCode()==new Integer(1).hashCode());
   System.out.println(new String("zhang").equals(new String("zhang")));
   System.out.println(new String("zhang").hashCode()==new String("zhang").hashCode());
   System.out.println("\n");
   //使用者自定義的資料型別
   System.out.println(new Student("zhangsan",98.8).equals(new Student("zhangsan",98.8)));
   System.out.println(new Student("zhangsan",98.8).hashCode());
   System.out.println(new Student("zhangsan",98.8).hashCode());
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   if(this.score > obj.score)
    return 1;
   else
    return -1;
 }
}

輸出結果:


true
true
true
true
false
488676694
1211729930

重寫之後:


package IT;
public class App
{
  public static void main(String[] args)
  {
   System.out.println(new Student("zhangsan",98.8).equals(new Student("zhangsan",98.8)));
   System.out.println(new Student("zhangsan",98.8).hashCode());
   System.out.println(new Student("zhangsan",98.8).hashCode());
  }
}
class Student implements Comparable<Student>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return this.name "\t" this.score;
  }
 public int compareTo(Student obj)
 {
   if(this.score > obj.score)
    return 1;
   else
    return -1;
 }
 @Override
 public int hashCode()
 {
  return (int) (this.name.hashCode()*score);
 }
 @Override
 public boolean equals(Object obj)
 {
  Student cc = (Student)obj;
  return this.name==cc.name&&this.score==cc.score;
 }
}

輸出結果:


true
-2147483648
-2147483648

上面的5、6、7、8可以歸結為4個”凡是”,1個“邏輯”:

1、凡是把類物件放到容器中,相應的類都應該實現Object類中的toString()方法;
2、凡是需要進行比較排序的類都應該實現Comparable介面中的compareTo()方法;凡是把類物件放到以樹為內部結構的容器中都應該實現Comparable介面中的compareTo()方法
3、凡是把類物件放到以雜湊表為內部儲存結構的容器中,相應的類必須要實現equals方法和hashCode方法,這樣才符合雜湊表真實的邏輯功能.
4、邏輯上來講,只要兩個物件的內容相同,其地址(hashCode()返回值)以及這兩個物件就應該相同(equals())。

9、雜湊衝突的相關概念

本質上講就是:hash(物件1.hashCode())=hash2(物件2.hashCode()),即第一個物件的hashCode()方法返回的雜湊碼值帶入到雜湊函式後得到的索引位置與第二個物件的hashCode()方法返回的雜湊碼值帶入到雜湊函式後得到的索引位置相同,這就是雜湊衝突。

最常見的雜湊演算法是取模法。

下面簡單講講取模法的計算過程。

比如:陣列的長度是5。這時有一個資料是6。那麼如何把這個6存放到長度只有5的陣列中呢。按照取模法,計算6%5,結果是1,那麼就把6放到陣列下標是1的位置。那麼,7

就應該放到2這個位置。到此位置,哈斯衝突還沒有出現。這時,有個資料是11,按照取模法,11%5=1,也等於1。那麼原來陣列下標是1的地方已經有數了,是6。這時又計算出1這個位置,那麼陣列1這個位置,就必須儲存兩個數了。這時,就叫雜湊衝突。衝突之後就要按照順序來存放了。

如果資料的分佈比較廣泛,而且儲存資料的陣列長度比較大。

那麼雜湊衝突就比較少。否則衝突是很高的。

10、iterator介面的作用

重要方法:

boolean hasNext():是用來判斷當前遊標(迭代器)的後面是否存在元素,如果存在返回真,否則返回假
Object next():先返回當前遊標右邊的元素,然後遊標後移一個位置
void remove():不推薦使用iterator的remove()方法,而是推薦使用容器自帶的remove方法。

例項程式:


package IT;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class App
{
  public static void main(String[] args)
  {
   HashMap<String, Double> hashMap = new HashMap<String,Double>();
   hashMap.put("zhangsan", 88.6);
   hashMap.put("lisi", 69.0);
   hashMap.put("wanqwu", 100.0);
   hashMap.put("lisi", 69.0);
   Set<String> keySet = hashMap.keySet();
   Iterator<String> iterator = keySet.iterator();
   while(iterator.hasNext())
   {
    String key = iterator.next();//獲取迭代器右邊的元素,同時右移
    System.out.println(key hashMap.get(key));
   }
  }
}

思考題:


package IT;
import java.util.TreeSet;
public class App
{
  public static void main(String[] args)
  {
    TreeSet<Student> treeSet = new TreeSet<Student>();
    treeSet.add(new Student("zhangsan",98));
    treeSet.add(new Student("zhangsan",98));
    System.out.println(treeSet.size());
    System.out.println(treeSet);
    //本程式中並沒有重寫equals方法,但是treeSet將識別出兩個new Student("zhangsan",98)為相同的,因為內部資料結構嗎?
    System.out.println(new Student("zhangsan",98).equals(new Student("zhangsan",98)));
  }
}
class Student implements Comparable<Object>
{
  public String name;
  public double score;
  public Student(String name,double score)
  {
   this.name = name;
   this.score = score;
  }
  public String toString()
  {
   return name   "\t"   score;
  }
 @Override
 public int compareTo(Object obj)
 {
  Student cc = (Student)obj;
  return (int) (this.score - cc.score);
 }
}

更多關於java相關內容感興趣的讀者可檢視本站專題:《Java物件導向程式設計入門與進階教程》、《Java資料結構與演算法教程》、《Java操作DOM節點技巧總結》、《Java檔案與目錄操作技巧彙總》和《Java快取操作技巧彙總

希望本文所述對大家java程式設計有所幫助。

您可能感興趣的文章:

Java容器類的深入理解深入理解Java的Spring框架中的IOC容器Java多執行緒程式設計中的兩種常用併發容器講解Java的Swing程式設計中使用SwingWorker執行緒模式及頂層容器淺析Java的Spring框架中IOC容器容器的應用java容器詳細解析深入理解Java執行緒程式設計中的阻塞佇列容器迅速掌握Java容器中常用的ArrayList類與Vector類用法java併發容器CopyOnWriteArrayList實現原理及原始碼分析用java的spring實現一個簡單的IOC容器示例程式碼基於Java併發容器ConcurrentHashMap#put方法解析Java容器HashMap與HashTable詳解