目錄
1 數組和集合的對比
數組 | 集合 |
---|---|
可以存儲基本數據類型和對象 | 只能存儲對象(可用包裝類的形式存儲基本數據類型) |
長度固定 | 長度動態改變 |
定義時必須指定元素類型 | 默認Object類型 |
無法直接獲取實際存儲元素個數 | 可直接通過size()方法獲取元素個數 |
有序的分配連續空間 | 多個方式適應不同的場合 |
2 List
List的特點是:有序、元素可重複
實現類:ArrayList、LinkedList、Vector、Stack
2.1 ArrayList
ArrayList(Array數組,List列表),實現了長度可變的數組,本質上還是使用數組實現,所以和數組的特點類似。
2.1.1 特點
- 其中的元素是有順序的,按照元素添加的順序排列
- 默認長度爲10,內部會自動增大長度
- 允許元素重複添加
- 屬於泛型,如果不指明具體的類型默認爲Object,此時可以添加任意類型的元素。
- 如果指定具體的類型則只能添加對應類型的元素
2.1.2 常用方法
方法名 | 作用 |
---|---|
add(Object o) | 默認在末尾添加元素 |
add(int index, Object o) | 在指定位置添加元素 |
set(int index, Object o) | 修改指定位置的元素,返回被修改之前的元素 |
remove(Object o) | 根據元素值刪除,返回boolean值表示是否成功 |
remove(int index,Object o) | 刪除指定位置的元素,返回被刪除的元素 |
get(int index) | 根據位置獲取對應的元素 |
size() | 返回集合中的元素個數 |
isempty() | 檢查集合是否爲空(實際就是判斷 size==0) |
indexOf(Object o) | 返回要查找元素的位置(不存在就返回-1) |
contains(Object o) | 返回boolean值表示是否存在要查找的元素(實際就是判斷 indexOf >= 0) |
clear() | 清空集合 |
toArray() | 將集合轉換成Object數組 |
asList(T…a) | 將數組轉換成集合(靜態方法,可用於創建ArrayList對象時使用) |
2.1.3 遍歷元素方式
//普通循環
for(int i=0; i<list.size(); i++) {
System.out.print(list.get(i) + "\t");
}
//增強for循環
for(Integer num: list) {
System.out.print(num + "\t");
}
//迭代器遍歷
Iterator<Integer> iterator = list.iterator() ; //創建迭代器對象
while(iterator.hasNext()) { //判斷是否存在下一個元素
Integer num = iterator.next() ; //提取當前元素
System.out.print(num + "\t");
}
其中的迭代器遍歷方式,如果學過軟件設計模式就知道,其中有一個迭代器模式。將要遍歷的集合交給迭代器來處理,使內部數據不會暴露,而且可以根據自己的需求創建不同的迭代器從而實現不同的遍歷方式。
2.2 Vector
和ArrayList相似,都是用數組實現,基本方法也類似。
2.2.1 Vector和ArrayList的區別
Vector | ArrayList |
---|---|
同步,線程安全 | 異步,線程不安全 |
執行效率低 | 相較於Vector執行效率高 |
遍歷方式:迭代器遍歷、枚舉遍歷 | 遍歷方式:迭代器遍歷 |
查看源碼可知在Vector中的大多數方法都是被synchronized修飾的,這個單詞翻譯過來就是 “同步” 的意思。被synchronized修飾的方法能夠保證線程的安全。
2.2.2 枚舉遍歷元素
//使用枚舉遍歷
Enumeration<Integer> e = list.elements() ;
while(e.hasMoreElements()) { //判斷是否存在下一個元素
Integer now = e.nextElement() ; //提取當前元素
System.out.print(now + "\t");
}
枚舉遍歷和迭代器遍歷類似,但枚舉遍歷是比較老的技術已過時,最好使用迭代器遍歷,用Iterator替代Enumeration
2.2.3 使用Vector建議
Vector已過時,不建議使用。如果需要考慮安全性的地方,作爲代替可以使用Collections類中的synchronizedList(List list)方法將集合變爲一個線程安全的集合
LinkedList
當需要頻繁插入和刪除元素時適用,本質上使用雙向鏈式存儲。具有List的所有方法。實現了隊列Queue接口
特有方法 | 作用 |
---|---|
addFirst(Object o) | 在首部添加元素 |
addLast(Object o) | 在末尾添加元素,效果和默認的add()效果一樣 |
getFirst() | 返回第一個元素 |
getLast() | 返回最後一個元素 |
removeFirst() | 刪除第一個元素 |
removeLast() | 刪除最後一個元素 |
2.3 LinkList
LinkedList和ArrayList的最大區別就是ArrayList基於數組實現,而LinkedList是基於鏈表實現的。所以當需要進行大量插入、刪除等操作時,可以選擇使用LinkList
3 Set
Set的特點是:
- 無序(元素順序與放入順序無關),從而不能按索引訪問元素(沒有get(int index)方法)
- 不可重複
實現:HashSet、TreeSet
3.1 HashSet
3.1.1 特點
- 基於哈希算法的集合,以哈希表的形式存儲
- 由於根據哈希算法進行快速查找,則操作速度快,效率高
- 添加相同元素時只會添加一次,多餘的添加不進去
- 根據地址判斷兩個元素是否相同而不是根據數據值判斷
3.1.2 常用方法
由於Set也是實現了Collection接口,所以其中的方法都存在,例如size()、clear()、remove()、contains()等等
方法名 | 作用 |
---|---|
addAll(Collection c) | 將List轉換成Set(可用來去重) |
3.1.3 判斷元素是否重複的過程:
- 添加元素時自動調用要存入對象的hashCode()方法,得到hashCode值(若沒有重寫hashCode()方法,在Object類中就是返回內存地址)
- 根據hashCode值,通過哈希算法確定在哈希表中存放的位置
- 判斷該位置是否已經有元素,沒有元素就直接放入,若有元素就調用equals()方法進行比較,返回true則認爲是重複元素,直接捨棄,否則在當前位置以鏈表的形式追加
3.2 TreeSet
3.2.1 特點
- 用於對元素進行排序,但仍然滿足元素順序和放入順序無關的特點
- 基於二叉樹的集合
3.2.2 排序依據:
- 元素類型本身具有自然順序就按此排序,例如數字有大小順序,字符串有字典序
- 元素類型沒有自然順序,直接將元素添加到TreeSet集合中會報錯
則要讓被排序的對象實現comparable接口,讓其具有可比較性,並實現其中的compareTo()方法。或者定義一個比較器(實現Comparator接口的類),並實現compare()方法,然後在定義TreeSet對象的時候將比較器作爲參數傳入。若同時使用這兩種方法則只會選擇比較器的方式排序。
public class TreeSet1 {
public static void main(String[] args) {
TreeSet<User> t = new TreeSet<User>(new UserComparator()) ; //比較器作爲參數
t.add(new User(19, "小明")) ;
t.add(new User(18, "小李")) ;
System.out.println(t);
}
}
public class UserComparator implements Comparator<User> { //實現Comparator接口的比較器類
public int compare(User o1, User o2) {
if(o1.getAge() > o2.getAge()) //降序
return -1 ;
else if(o1.getAge() < o2.getAge())
return 1 ;
else
return 0 ; //返回0代表重複
}
}
public class User {
private int age ;
private String name ;
public User(int age, String name) {
this.age = age ;
this.name = name ;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "User [age=" + age + ", name=" + name + "]";
}
}
判斷重複的依據是添加的兩個元素通過compareTo()進行比較時,若返回0則代表重複
4 Map
專門用來處理 鍵(key)值(value)映射數據 的集合,根據key實現對value的操作
實現類:HashMap、Hashtable、Proprties
4.1 鍵值對(key-value):
鍵值對是一種映射關係,由key可以映射到對應的value
特點:
- key必須唯一
- 一個key只能對應一個value,但一個value可以對應多個key(key不能重複,value可以重複)
- 無法保證元素的順序和添加順序一致,從而不能按索引訪問元素(可用key訪問)
4.2 HashMap
基於哈希算法的集合,以哈希表形式存儲
HashMap屬於泛型,但泛型參數有兩個,分別代表鍵和值。HashMap<k, v>
4.2.1 常用方法
方法名 | 作用 |
---|---|
put(Object key, Object value) | 添加元素,包括鍵和值 (輸入的key重複時作爲修改value) |
get(Object key) | 根據key獲取對應的value |
remove(Object key) | 根據key刪除對應的鍵值對 |
containsKey(Object key) | 查看是否包含指定的key |
containsValue(Object value) | 查看是否包含指定的value |
keySet() | 返回包含所有key的Set集合 |
4.2.2 HashSet和HashMap的關係
之前說的HashSet元素不可重複,本質上就是創建了一個HashMap,由於key是唯一的,所以將Set中的元素作爲key就實現了元素不重複
4.2.3 遍歷元素方法
需要注意的是Map本身沒有遍歷方法
//通過setKey()方法獲得key集合,再通過key進行遍歷
Set<Integer> keys = m.keySet() ;
for(Integer key : keys) {
System.out.println(key + " "+ m.get(key));
}
//通過values()方法獲得所有的value,再通過value進行遍歷
Collection<String> values = m.values() ;
for(String value: values) {
System.out.println(value); //沒有辦法從值得到鍵
}
//通過entrySet()獲取所有鍵值對,返回一個Set集合。遍歷所有的key和value
Set< Entry<Integer, String> > entris = m.entrySet() ; //Entry是Map裏的內部接口,表示鍵值對
Iterator< Entry<Integer, String> > it = entris.iterator() ;
while(it.hasNext()) {
Entry<Integer, String> entry = it.next() ; //每一個元素的類型都用Entry表示就行
System.out.println(entry.getKey() + " "+ entry.getValue());
}
4.3 Hashtable
4.3.1 Hashtable和HashMap的區別
和HashMap基本用法類似,區別如下
Hashtable | HashMap |
---|---|
同步的,線程安全 | 異步的,線程不安全 |
key和value都不允許爲null(編譯不報錯,運行時報錯NullPointer) | key和value都允許爲null |
可以使用Iterator和Enumerration遍歷 | 不能用Enumerration遍歷 |
Hashtable是一種過時的東西,一般使用hashMap就可以了
4.4 Properties
Properties繼承自Hashtable,一般只用來存儲字符串鍵值對(鍵和值都是字符串)
在創建對象是不需要再考慮泛型,默認就是字符串
4.4.1 常用方法
方法 | 作用 |
---|---|
setProperty(String key, String value) | 添加、修改元素 (默認參數類型就是字符串) |
getProperty(String key) | 根據key獲取對應元素的value |
propertyNames() | 返回一個枚舉類型的key集合 |
4.4.2 讀取屬性文件
Properties常用來讀取屬性文件的內容
4.4.2.1 屬性文件
- 一般是以.properties爲後綴的文件,但實際上不管是什麼類型的文件只要符合格式要求就行
- 格式要求:屬性名=屬性值
- 只支持ISO-8859-1編碼,不支持中文,但可以通過IDE自動進行編碼轉換
讀取方法:
使用load(InputStream inStream)方法就可以自動將屬性文件中的內容存入到Properties對象中。關鍵是要讀取的屬性對象要通過輸入流的形式作爲參數傳遞進來。要得到流,就要獲得類加載器,要得到類加載器又要得到運行時類。所以參數需要一層層調用方法才能獲得輸入流文件
Properties p = new Properties() ;
//讀取屬性文件
p.load(Properties1.class //.class獲得運行時類的字節碼文件
.getClassLoader() //得到運行時類後獲得類加載器,用來加載類路徑下的資源(文件)
.getResourceAsStream("data.properties") //將文件作爲流獲取,符合load()方法參數需要輸入流文件
);
System.out.println(p);
System類中含有一個getProperties()方法,返回一個Properties對象,可以獲得系統屬性
5 Collections類
Collections是一個工具類,提供了集合操作的相關方法,例如排序、查找、求最值等。既然是工具類,則大部分的方法都是靜態的,直接拿來用就好了
5.1 常用方法
方法名 | 作用 |
---|---|
addAll(Collection c, Objetc… elements) | 向指定的集合中添加任意個數的元素 |
max(Collection c) | 求出指定集合中的最大值 |
min(Collection c) | 求出指定集合中的最小值 |
sort(Collection c) | 對指定集合中的元素進行排序 |
reverse(Collection c) | 對指定集合中的元素順序進行反轉 |
swap(Collection c, int i, int j) | 將i,j兩個位置的元素交換 |
5.2 Collections和Collection的區別
Collection | Collections |
---|---|
接口 | 工具類 |
List、Set實現該接口 | 提供集合的相關操作 |