本文實例講述了java開發中的容器概念、分類與用法。分享給大家供大家參考,具體如下:
1、容器的概念
在java當中,如果有一個類專門用來存放其它類的對象,這個類就叫做容器,或者就叫做集合,集合就是將若干性質相同或相近的類對象組合在一起而形成的一個整體
2、容器與數組的關系
之所以需要容器:
① 數組的長度難以擴充
② 數組中數據的類型必須相同
容器與數組的區別與聯系:
① 容器不是數組,不能通過下標的方式訪問容器中的元素
② 數組的所有功能通過arraylist容器都可以實現,只是實現的方式不同
③ 如果非要將容器當做一個數組來使用,通過toarraylist方法返回的就是一個數組
示例程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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]); } } } |
輸出結果:
1
2
3
4
|
12 10 35 100 |
通過arraylist容器獲取一個數組arr:
1
2
3
4
|
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():返回容器中的元素數
實例程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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()); } } |
運行結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
原容器中的元素為: [ 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存儲數據。
實例程序:
1
2
3
4
5
6
7
8
9
10
11
12
|
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) |
運行結果:
1
2
3
4
|
set輸出的結果: set( 100 , 50 , 500 , 10 , 200 ) map輸出的結果: map(hadoop -> 80.0 , spark -> 90.0 , scala -> 100.0 , java -> 60.0 ) |
實例程序:
1
2
3
4
5
6
7
8
9
|
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) |
運行結果:
1
2
3
|
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()方法之前)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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; } } |
輸出結果:
1
2
3
4
|
-----凡是java中自帶的數據類型都已經重寫完了tostring()方法!--- 2 zhang it.student @1af2f973 |
實例2:(重寫完tostring()方法之后)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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; } } |
輸出結果:
1
|
[zhangsan 89.8 , lisi 90.0 , wangwu 60.6 ] |
6、comparable接口中的compareto()方法:凡是需要進行比較排序的類都應該實現comparable接口中的compareto()方法;凡是把類對象放到以樹為內部結構的容器中都應該實現comparable接口中的compareto()方法
實例1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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進行升序 } } |
輸出結果:
1
2
3
4
|
wangwu 60.6 wangting 85.6 zhangsan 89.8 lisi 90.0 |
實例2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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 ; } } |
輸出結果:
1
2
3
4
|
zhangsan 60.6 wangwu 60.6 wangting 85.6 lisi 90.0 |
7、凡是把類對象放到以哈希表為內部存儲結構的容器中,相應的類必須要實現equals方法和hashcode方法,這樣才符合哈希表真實的邏輯功能.
實例程序1:(為重寫之前)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
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 ; } } |
輸出結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
先測試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:重寫之后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
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; } } |
輸出結果:
1
2
3
4
5
|
測試用戶自定義的數據類型--重寫兩個方法之后: wangwu 66.9 beijing zhangsan 88.8 beijing lisi 88.8 beijing 重寫過后:相同的對象會被覆蓋! |
8、重要的一個邏輯:邏輯上來講,只要兩個對象的內容相同,其地址(hashcode()返回值)以及這兩個對象就應該相同(equals()),
實例程序(為重寫之前):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
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 ; } } |
輸出結果:
1
2
3
4
5
6
7
|
true true true true false 488676694 1211729930 |
重寫之后:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
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; } } |
輸出結果:
1
2
3
|
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方法。
實例程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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)); } } } |
思考題:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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程序設計有所幫助。
原文鏈接:http://blog.csdn.net/a2011480169/article/details/52047600