Java013-集合

姚根深發表於2019-01-19

集合框架(重點理解):
用於儲存資料的容器。
特點:
1:物件封裝資料,物件多了也需要儲存。集合用於儲存物件。
2:物件的個數確定可以使用陣列,但是不確定怎麼辦?可以用集合。因為集合是可變長度的。

集合和陣列的區別:
1:陣列是固定長度的;集合可變長度的。
2:陣列可以儲存基本資料型別,也可以儲存引用資料型別;集合只能儲存引用資料型別。
3:陣列儲存的元素必須是同一個資料型別;集合儲存的物件可以是不同資料型別。

資料結構:就是容器中儲存資料的方式。

對於集合容器,有很多種。因為每一個容器的自身特點不同,其實原理在於每個容器的內部資料結構不同。
集合容器在不斷向上抽取過程中。出現了集合體系。
在使用一個體系時,原則:參閱頂層內容。建立底層物件。


–< java.util >– Collection介面:
Collection:
|–List:有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素可以重複。
|–Set:無序(存入和取出順序有可能不一致),不可以儲存重複元素。必須保證元素唯一性。

1,新增:
add(object):新增一個元素
addAll(Collection) :新增一個集合中的所有元素。
2,刪除:
clear():將集合中的元素全刪除,清空集合。
remove(obj) :刪除集合中指定的物件。注意:刪除成功,集合的長度會改變。
removeAll(collection) :刪除部分元素。部分元素和傳入Collection一致。
3,判斷:
boolean contains(obj) :集合中是否包含指定元素 。
boolean containsAll(Collection) :集合中是否包含指定的多個元素。
boolean isEmpty():集合中是否有元素。
4,獲取:
int size():集合中有幾個元素。
5,取交集:
boolean retainAll(Collection) :對當前集合中保留和指定集合中的相同的元素。如果兩個集合元素相同,返回flase;如果retainAll修改了當前集合,返回true。
6,獲取集合中所有元素:
Iterator iterator():迭代器
7,將集合變成陣列:

toArray();

–< java.util >– Iterator介面:
迭代器:是一個介面。作用:用於取集合中的元素。
boolean hasNext()  如果仍有元素可以迭代,則返回 true。
 E next()   返回迭代的下一個元素。
void remove()  從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操作)。

每一個集合都有自己的資料結構,都有特定的取出自己內部元素的方式。為了便於操作所有的容器,取出元素。將容器內部的取出方式按照一個統一的規則向外提供,這個規則就是Iterator介面。
也就說,只要通過該介面就可以取出Collection集合中的元素,至於每一個具體的容器依據自己的資料結構,如何實現的具體取出細節,這個不用關心,這樣就降低了取出元素和具體集合的耦合性。

Iterator it = coll.iterator();//獲取容器中的迭代器物件,至於這個物件是是什麼不重要。這物件肯定符合一個規則Iterator介面。

public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add(“abc0”);
coll.add(“abc1”);
coll.add(“abc2”);
//————–方式1———————-
Iterator it = coll.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//—————方式2用此種———————-
for(Iterator it = coll.iterator();it.hasNext(); ){
System.out.println(it.next());
}

}

–< java.util >– List介面:
List本身是Collection介面的子介面,具備了Collection的所有方法。現在學習List體系特有的共性方法,查閱方法發現List的特有方法都有索引,這是該集合最大的特點。

List:有序(元素存入集合的順序和取出的順序一致),元素都有索引。元素可以重複。
|–ArrayList:底層的資料結構是陣列,執行緒不同步,ArrayList替代了Vector,查詢元素的速度非常快。
|–LinkedList:底層的資料結構是連結串列,執行緒不同步,增刪元素的速度非常快。
|–Vector:底層的資料結構就是陣列,執行緒同步的,Vector無論查詢和增刪都巨慢。

1,新增:
add(index,element) :在指定的索引位插入元素。
addAll(index,collection) :在指定的索引位插入一堆元素。
2,刪除:
remove(index) :刪除指定索引位的元素。 返回被刪的元素。
3,獲取:
Object get(index) :通過索引獲取指定元素。
int indexOf(obj) :獲取指定元素第一次出現的索引位,如果該元素不存在返回-1;
所以,通過-1,可以判斷一個元素是否存在。
int lastIndexOf(Object o) :反向索引指定元素的位置。
List subList(start,end) :獲取子列表。
4,修改:
Object set(index,element) :對指定索引位進行元素的修改。
5,獲取所有元素:
ListIterator listIterator():list集合特有的迭代器。

List集合支援對元素的增、刪、改、查。

List集合因為角標有了自己的獲取元素的方式: 遍歷。
for(int x=0; x<list.size(); x++){
sop(“get:”+list.get(x));
}
在進行list列表元素迭代的時候,如果想要在迭代過程中,想要對元素進行操作的時候,比如滿足條件新增新元素。會發生.ConcurrentModificationException併發修改異常。
導致的原因是:
集合引用和迭代器引用在同時操作元素,通過集合獲取到對應的迭代器後,在迭代中,進行集合引用的元素新增,迭代器並不知道,所以會出現異常情況。
如何解決呢?
既然是在迭代中對元素進行操作,找迭代器的方法最為合適.可是Iterator中只有hasNext,next,remove方法.通過查閱的它的子介面,ListIterator,發現該列表迭代器介面具備了對元素的增、刪、改、查的動作。

ListIterator是List集合特有的迭代器。
ListIterator it = list.listIterator;//取代Iterator it = list.iterator;
方法摘要
void add(E e) 將指定的元素插入列表(可選操作)。
boolean hasNext() 以正向遍歷列表時,如果列表迭代器有多個元素,則返回 true(換句話說,如果 next 返回一個元素而不是丟擲異常,則返回 true)。
boolean hasPrevious() 如果以逆向遍歷列表,列表迭代器有多個元素,則返回 true。
 E next() 返回列表中的下一個元素。
int nextIndex() 返回對 next 的後續呼叫所返回元素的索引。
 E previous() 返回列表中的前一個元素。
int previousIndex() 返回對 previous 的後續呼叫所返回元素的索引。
void remove() 從列表中移除由 next 或 previous 返回的最後一個元素(可選操作)。
void set(E e) 用指定元素替換 next 或 previous 返回的最後一個元素(可選操作)。

可變長度陣列的原理:
當元素超出陣列長度,會產生一個新陣列,將原陣列的資料複製到新陣列中,再將新的元素新增到新陣列中。
ArrayList:是按照原陣列的50%延長。構造一個初始容量為 10 的空列表。
Vector:是按照原陣列的100%延長。

注意:對於list集合,底層判斷元素是否相同,其實用的是元素自身的equals方法完成的。所以建議元素都要複寫equals方法,建立元素物件自己的比較相同的條件依據。

LinkedList:的特有方法。
addFirst();
addLast();
在jdk1.6以後。
offerFirst();
offerLast();

getFirst():獲取連結串列中的第一個元素。如果連結串列為空,丟擲NoSuchElementException;
getLast();
在jdk1.6以後。
peekFirst();獲取連結串列中的第一個元素。如果連結串列為空,返回null。
peekLast();

removeFirst():獲取連結串列中的第一個元素,但是會刪除連結串列中的第一個元素。如果連結串列為空,丟擲NoSuchElementException
removeLast();
在jdk1.6以後。
pollFirst();獲取連結串列中的第一個元素,但是會刪除連結串列中的第一個元素。如果連結串列為空,返回null。

pollLast();

–< java.util >– Set介面:
Set介面中的方法和Collection中方法一致的。Set介面取出方式只有一種,迭代器。
|–HashSet:底層資料結構是雜湊表,執行緒是不同步的。無序,高效;
HashSet集合保證元素唯一性:通過元素的hashCode方法,和equals方法完成的。
當元素的hashCode值相同時,才繼續判斷元素的equals是否為true。
如果為true,那麼視為相同元素,不存。如果為false,那麼儲存。
如果hashCode值不同,那麼不判斷equals,從而提高物件比較的速度。

  |--LinkedHashSet:有序,hashset的子類。

|–TreeSet:對Set集合中的元素的進行指定順序的排序。不同步。TreeSet底層的資料結構就是二叉樹。

雜湊表的原理:
1,對物件元素中的關鍵字(物件中的特有資料),進行雜湊演算法的運算,並得出一個具體的演算法值,這個值 稱為雜湊值。
2,雜湊值就是這個元素的位置。
3,如果雜湊值出現衝突,再次判斷這個關鍵字對應的物件是否相同。如果物件相同,就不儲存,因為元素重複。如果物件不同,就儲存,在原來物件的雜湊值基礎 +1順延。
4,儲存雜湊值的結構,我們稱為雜湊表。
5,既然雜湊表是根據雜湊值儲存的,為了提高效率,最好保證物件的關鍵字是唯一的。
這樣可以儘量少的判斷關鍵字對應的物件是否相同,提高了雜湊表的操作效率。

對於ArrayList集合,判斷元素是否存在,或者刪元素底層依據都是equals方法。
對於HashSet集合,判斷元素是否存在,或者刪除元素,底層依據的是hashCode方法和equals方法。

TreeSet:
用於對Set集合進行元素的指定順序排序,排序需要依據元素自身具備的比較性。
如果元素不具備比較性,在執行時會發生ClassCastException異常。
所以需要元素實現Comparable介面,強制讓元素具備比較性,複寫compareTo方法。
依據compareTo方法的返回值,確定元素在TreeSet資料結構中的位置。
TreeSet方法保證元素唯一性的方式:就是參考比較方法的結果是否為0,如果return 0,視為兩個物件重複,不存。

注意:在進行比較時,如果判斷元素不唯一,比如,同姓名,同年齡,才視為同一個人。
在判斷時,需要分主要條件和次要條件,當主要條件相同時,再判斷次要條件,按照次要條件排序。

TreeSet集合排序有兩種方式,Comparable和Comparator區別:
1:讓元素自身具備比較性,需要元素物件實現Comparable介面,覆蓋compareTo方法。
2:讓集合自身具備比較性,需要定義一個實現了Comparator介面的比較器,並覆蓋compare方法,並將該類物件作為實際引數傳遞給TreeSet集合的建構函式。
第二種方式較為靈活。


Map集合:
|–Hashtable:底層是雜湊表資料結構,是執行緒同步的。不可以儲存null鍵,null值。
|–HashMap:底層是雜湊表資料結構,是執行緒不同步的。可以儲存null鍵,null值。替代了Hashtable.
|–TreeMap:底層是二叉樹結構,可以對map集合中的鍵進行指定順序的排序。

Map集合儲存和Collection有著很大不同:
Collection一次存一個元素;Map一次存一對元素。
Collection是單列集合;Map是雙列集合。
Map中的儲存的一對元素:一個是鍵,一個是值,鍵與值之間有對應(對映)關係。
特點:要保證map集合中鍵的唯一性。

1,新增。
put(key,value):當儲存的鍵相同時,新的值會替換老的值,並將老值返回。如果鍵沒有重複,返回null。
void putAll(Map);
2,刪除。
void clear():清空
value remove(key) :刪除指定鍵。
3,判斷。
boolean isEmpty():
boolean containsKey(key):是否包含key
boolean containsValue(value) :是否包含value
4,取出。
int size():返回長度
value get(key) :通過指定鍵獲取對應的值。如果返回null,可以判斷該鍵不存在。當然有特殊情況,就是在hashmap集合中,是可以儲存null鍵null值的。
Collection values():獲取map集合中的所有的值。
5,想要獲取map中的所有元素:
原理:map中是沒有迭代器的,collection具備迭代器,只要將map集合轉成Set集合,可以使用迭代器了。之所以轉成set,是因為map集合具備著鍵的唯一性,其實set集合就來自於map,set集合底層其實用的就是map的方法。
★ 把map集合轉成set的方法:
Set keySet();
Set entrySet();//取的是鍵和值的對映關係。
Entry就是Map介面中的內部介面;

為什麼要定義在map內部呢?entry是訪問鍵值關係的入口,是map的入口,訪問的是map中的鍵值對。

取出map集合中所有元素的方式一:keySet()方法。
可以將map集合中的鍵都取出存放到set集合中。對set集合進行迭代。迭代完成,再通過get方法對獲取到的鍵進行值的獲取。
Set keySet = map.keySet();
Iterator it = keySet.iterator();
while(it.hasNext()) {
Object key = it.next();
Object value = map.get(key);
System.out.println(key+”:”+value);

}

取出map集合中所有元素的方式二:entrySet()方法。
Set entrySet = map.entrySet();
Iterator it = entrySet.iterator();
while(it.hasNext()) {
Map.Entry me = (Map.Entry)it.next();
System.out.println(me.getKey()+”::::”+me.getValue());

}

使用集合的技巧:
看到Array就是陣列結構,有角標,查詢速度很快。
看到link就是連結串列結構:增刪速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
看到hash就是雜湊表,就要想要雜湊值,就要想到唯一性,就要想到存入到該結構的中的元素必須覆蓋hashCode,equals方法。
看到tree就是二叉樹,就要想到排序,就想要用到比較。
比較的兩種方式:
一個是Comparable:覆蓋compareTo方法;
一個是Comparator:覆蓋compare方法。
LinkedHashSet,LinkedHashMap:這兩個集合可以保證雜湊表有存入順序和取出順序一致,保證雜湊表有序。

集合什麼時候用?
當儲存的是一個元素時,就用Collection。當儲存物件之間存在著對映關係時,就使用Map集合。

保證唯一,就用Set。不保證唯一,就用List。

Collections:它的出現給集合操作提供了更多的功能。這個類不需要建立物件,內部提供的都是靜態方法。
靜態方法:
Collections.sort(list);//list集合進行元素的自然順序排序。
Collections.sort(list,new ComparatorByLen());//按指定的比較器方法排序。
class ComparatorByLen implements Comparator<String>{
public int compare(String s1,String s2){
int temp = s1.length()-s2.length();
return temp==0?s1.compareTo(s2):temp;
}
}
Collections.max(list); //返回list中字典順序最大的元素。
int index = Collections.binarySearch(list,”zz”);//二分查詢,返回角標。
Collections.reverseOrder();//逆向反轉排序。
Collections.shuffle(list);//隨機對list中的元素進行位置的置換。

將非同步集合轉成同步集合的方法:Collections中的 XXX synchronizedXXX(XXX);
List synchronizedList(list);
Map synchronizedMap(map);
原理:定義一個類,將集合所有的方法加同一把鎖後返回。

Collection 和 Collections的區別:
Collections是個java.util下的類,是針對集合類的一個工具類,提供一系列靜態方法,實現對集合的查詢、排序、替換、執行緒安全化(將非同步的集合轉換成同步的)等操作。

Collection是個java.util下的介面,它是各種集合結構的父介面,繼承於它的介面主要有Set和List,提供了關於集合的一些操作,如插入、刪除、判斷一個元素是否其成員、遍歷等。

Arrays:
用於運算元組物件的工具類,裡面都是靜態方法。
asList方法:將陣列轉換成list集合。
String[] arr = {“abc”,”kk”,”qq”};
List<String> list = Arrays.asList(arr);//將arr陣列轉成list集合。
將陣列轉換成集合,有什麼好處呢?用aslist方法,將陣列變成集合;
可以通過list集合中的方法來運算元組中的元素:isEmpty()、contains、indexOf、set;
注意(侷限性):陣列是固定長度,不可以使用集合物件增加或者刪除等,會改變陣列長度的功能方法。比如add、remove、clear。(會報不支援操作異常UnsupportedOperationException);
如果陣列中儲存的引用資料型別,直接作為集合的元素可以直接用集合方法操作。
如果陣列中儲存的是基本資料型別,asList會將陣列實體作為集合元素存在。

集合變陣列:用的是Collection介面中的方法:toArray();
如果給toArray傳遞的指定型別的資料長度小於了集合的size,那麼toArray方法,會自定再建立一個該型別的資料,長度為集合的size。
如果傳遞的指定的型別的陣列的長度大於了集合的size,那麼toArray方法,就不會建立新陣列,直接使用該陣列即可,並將集合中的元素儲存到陣列中,其他為儲存元素的位置預設值null。
所以,在傳遞指定型別陣列時,最好的方式就是指定的長度和size相等的陣列。

將集合變成陣列後有什麼好處?限定了對集合中的元素進行增刪操作,只要獲取這些元素即可。

Jdk5.0新特性:

Collection在jdk1.5以後,有了一個父介面Iterable,這個介面的出現的將iterator方法進行抽取,提高了擴充套件性。

增強for迴圈:foreach語句,foreach簡化了迭代器。
格式:// 增強for迴圈括號裡寫兩個引數,第一個是宣告一個變數,第二個就是需要迭代的容器
for( 元素型別 變數名 : Collection集合 & 陣列 ) {

}
高階for迴圈和傳統for迴圈的區別:
高階for迴圈在使用時,必須要明確被遍歷的目標。這個目標,可以是Collection集合或者陣列,如果遍歷Collection集合,在遍歷過程中還需要對元素進行操作,比如刪除,需要使用迭代器。
如果遍歷陣列,還需要對陣列元素進行操作,建議用傳統for迴圈因為可以定義角標通過角標操作元素。如果只為遍歷獲取,可以簡化成高階for迴圈,它的出現為了簡化書寫。

高階for迴圈可以遍歷map集合嗎?不可以。但是可以將map轉成set後再使用foreach語句。

1)、作用:對儲存物件的容器進行迭代: 陣列 collection map
2)、增強for迴圈迭代陣列:
String [] arr = {“a”, “b”, “c”};//陣列的靜態定義方式,只試用於陣列首次定義的時候
for(String s : arr) {
System.out.println(s);
}
3)、單列集合 Collection:
List list = new ArrayList();
list.add(“aaa”);
// 增強for迴圈, 沒有使用泛型的集合能不能使用增強for迴圈迭代?能
for(Object obj : list) {
String s = (String) obj;
System.out.println(s);
}
4)、雙列集合 Map:
Map map = new HashMap();
map.put(“a”, “aaa”);
// 傳統方式:必須掌握這種方式
Set entrys = map.entrySet(); // 1.獲得所有的鍵值對Entry物件
iter = entrys.iterator(); // 2.迭代出所有的entry
while(iter.hasNext()) {
Map.Entry entry = (Entry) iter.next();
String key = (String) entry.getKey(); // 分別獲得key和value
String value = (String) entry.getValue();
System.out.println(key + “=” + value);
}
// 增強for迴圈迭代:原則上map集合是無法使用增強for迴圈來迭代的,因為增強for迴圈只能針對實現了Iterable介面的集合進行迭代;Iterable是jdk5中新定義的介面,就一個方法iterator方法,只有實現了Iterable介面的類,才能保證一定有iterator方法,java有這樣的限定是因為增強for迴圈內部還是用迭代器實現的,而實際上,我們可以通過某種方式來使用增強for迴圈。
for(Object obj : map.entrySet()) {
Map.Entry entry = (Entry) obj; // obj 依次表示Entry
System.out.println(entry.getKey() + “=” + entry.getValue());
}
5)、集合迭代注意問題:在迭代集合的過程中,不能對集合進行增刪操作(會報併發訪問異常);可以用迭代器的方法進行操作(子類listIterator:有增刪的方法)。
6)、增強for迴圈注意問題:在使用增強for迴圈時,不能對元素進行賦值;
int[] arr = {1,2,3};
for(int num : arr) {
num = 0; //不能改變陣列的值
}

System.out.println(arr[1]); //2

可變引數(…):用到函式的引數上,當要操作的同一個型別元素個數不確定的時候,可是用這個方式,這個引數可以接受任意個數的同一型別的資料。

和以前接收陣列不一樣的是:
以前定義陣列型別,需要先建立一個陣列物件,再將這個陣列物件作為引數傳遞給函式。現在,直接將陣列中的元素作為引數傳遞即可。底層其實是將這些元素進行陣列的封裝,而這個封裝動作,是在底層完成的,被隱藏了。所以簡化了使用者的書寫,少了呼叫者定義陣列的動作。
如果在引數列表中使用了可變引數,可變引數必須定義在引數列表結尾(也就是必須是最後一個引數,否則編譯會失敗。)。

如果要獲取多個int數的和呢?可以使用將多個int數封裝到陣列中,直接對陣列求和即可。

靜態匯入:匯入了類中的所有靜態成員,簡化靜態成員的書寫。

import static java.util.Collections.*; //匯入了Collections類中的所有靜態成員

列舉:關鍵字 enum
問題:物件的某個屬性的值不能是任意的,必須為固定的一組取值其中的某一個;
解決辦法:
1)、在setGrade方法中做判斷,不符合格式要求就丟擲異常;
2)、直接限定使用者的選擇,通過自定義類模擬列舉的方式來限定使用者的輸入,寫一個Grade類,私有建構函式,對外提供5個靜態的常量表示類的例項;
3)、jdk5中新定義了列舉型別,專門用於解決此類問題;

4)、列舉就是一個特殊的java類,可以定義屬性、方法、建構函式、實現介面、繼承類;

自動拆裝箱:java中資料型別分為兩種 : 基本資料型別 引用資料型別(物件)
在 java程式中所有的資料都需要當做物件來處理,針對8種基本資料型別提供了包裝類,如下:
int –> Integer
byte –> Byte
short –> Short
long –> Long
char –> Character
double –> Double
float –> Float
boolean –> Boolean

jdk5以前基本資料型別和包裝類之間需要互轉:
基本—引用 Integer x = new Integer(x);
引用—基本 int num = x.intValue();
1)、Integer x = 1; x = x + 1; 經歷了什麼過程?裝箱 à 拆箱 à 裝箱;
2)、為了優化,虛擬機器為包裝類提供了緩衝池,Integer池的大小 -128~127 一個位元組的大小;

3)、String池:Java為了優化字串操作 提供了一個緩衝池;

泛型:jdk1.5版本以後出現的一個安全機制。表現格式:< >
好處:
1:將執行時期的問題ClassCastException問題轉換成了編譯失敗,體現在編譯時期,程式設計師就可以解決問題。
2:避免了強制轉換的麻煩。

只要帶有<>的類或者介面,都屬於帶有型別引數的類或者介面,在使用這些類或者介面時,必須給<>中傳遞一個具體的引用資料型別。

泛型技術:其實應用在編譯時期,是給編譯器使用的技術,到了執行時期,泛型就不存在了。
為什麼? 因為泛型的擦除:也就是說,編輯器檢查了泛型的型別正確後,在生成的類檔案中是沒有泛型的。
在執行時,如何知道獲取的元素型別而不用強轉呢?
泛型的補償:因為儲存的時候,型別已經確定了是同一個型別的元素,所以在執行時,只要獲取到該元素的型別,在內部進行一次轉換即可,所以使用者不用再做轉換動作了。

什麼時候用泛型類呢?

當類中的操作的引用資料型別不確定的時候,以前用的Object來進行擴充套件的,現在可以用泛型來表示。這樣可以避免強轉的麻煩,而且將執行問題轉移到的編譯時期。

泛型在程式定義上的體現:
//泛型類:將泛型定義在類上。
class Tool<Q> {
private Q obj;
public void setObject(Q obj) {
this.obj = obj;
}
public Q getObject() {
return obj;
}
}
//當方法操作的引用資料型別不確定的時候,可以將泛型定義在方法上。
public <W> void method(W w) {
System.out.println(“method:”+w);
}
//靜態方法上的泛型:靜態方法無法訪問類上定義的泛型。如果靜態方法操作的引用資料型別不確定的時候,必須要將泛型定義在方法上。
public static <Q> void function(Q t) {
System.out.println(“function:”+t);
}
//泛型介面.
interface Inter<T> {
void show(T t);
}
class InterImpl<R> implements Inter<R> {
public void show(R r) {
System.out.println(“show:”+r);
}

}

泛型中的萬用字元:可以解決當具體型別不確定的時候,這個萬用字元就是 ? ;當操作型別時,不需要使用型別的具體功能時,只使用Object類中的功能。那麼可以用 ? 萬用字元來表未知型別。

泛型限定:
上限:?extends E:可以接收E型別或者E的子型別物件。
下限:?super E:可以接收E型別或者E的父型別物件。

上限什麼時候用:往集合中新增元素時,既可以新增E型別物件,又可以新增E的子型別物件。為什麼?因為取的時候,E型別既可以接收E類物件,又可以接收E的子型別物件。

下限什麼時候用:當從集合中獲取元素進行操作的時候,可以用當前元素的型別接收,也可以用當前元素的父型別接收。

泛型的細節:
1)、泛型到底代表什麼型別取決於呼叫者傳入的型別,如果沒傳,預設是Object型別;
2)、使用帶泛型的類建立物件時,等式兩邊指定的泛型必須一致;
原因:編譯器檢查物件呼叫方法時只看變數,然而程式執行期間呼叫方法時就要考慮物件具體型別了;
3)、等式兩邊可以在任意一邊使用泛型,在另一邊不使用(考慮向後相容);
ArrayList<String> al = new ArrayList<Object>(); //錯
//要保證左右兩邊的泛型具體型別一致就可以了,這樣不容易出錯。
ArrayList<? extends Object> al = new ArrayList<String>();
al.add(“aa”); //錯
//因為集合具體物件中既可儲存String,也可以儲存Object的其他子類,所以新增具體的型別物件不合適,型別檢查會出現安全問題。 ?extends Object 代表Object的子型別不確定,怎麼能新增具體型別的物件呢?
public static void method(ArrayList<? extends Object> al) {
al.add(“abc”); //錯
//只能對al集合中的元素呼叫Object類中的方法,具體子型別的方法都不能用,因為子型別不確定。

}

API— java.lang.System: 屬性和行為都是靜態的。
long currentTimeMillis(); // 返回當前時間毫秒值
exit(); // 退出虛擬機器
Properties getProperties() ; // 獲取當前系統的屬性資訊

Properties prop = System.getProperties(); //獲取系統的屬性資訊,並將這些資訊儲存到Properties集合中。

System.setProperty(“myname”,”畢老師”); //給系統屬性資訊集新增具體的屬性資訊
//臨時設定方式:執行jvm時,可以通過jvm的引數進行系統屬性的臨時設定,可以在java命令的後面加入 –D<name>=<value> 用法:java –Dmyname=小明 類名。

String name = System.getProperty(“os.name”);//獲取指定屬性的資訊

//想要知道該系統是否是該軟體所支援的系統中的一個。
Set<String> hs = new HashSet<String>();
hs.add(“Windows XP”);
hs.add(“Windows 7”);
if(hs.contains(name))
System.out.println(“可以支援”);
else

System.out.println(“不支援”);

API— java.lang.Runtime: 類中沒有構造方法,不能建立物件。
但是有非靜態方法。說明該類中應該定義好了物件,並可以通過一個static方法獲取這個物件。用這個物件來呼叫非靜態方法。這個方法就是 static Runtime getRuntime();

這個Runtime其實使用單例設計模式進行設計。

class RuntimeDemo {
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
Process p = r.exec(“notepad.exe SystemDemo.java”);//執行指定的程式
Thread.sleep(4000);
p.destroy(); //殺掉程式
}

}

API— java.util.Math: 用於數學運算的工具類,屬性和行為都是靜態的。該類是final不允許繼承。

static double ceil(double a) ; //返回大於指定數值的最小整數
static double floor(double a) ; //返回小於指定數值的最大整數
static long round(double a) ; //四捨五入成整數
static double pow(double a, double b) ; //a的b次冪
static double random(); //返回0~1的偽隨機數

public static void main(String[] args) {
Random r = new Random();
for(int x=0; x<10; x++) {
//double d = Math.floor(Math.random()*10+1);
//int d = (int)(Math.random()*10+1);
int d = r.nextInt(10)+1;
System.out.println(d);
}

}

API— java.util.Date:日期類,月份從0-11;
/*
日期物件和毫秒值之間的轉換。
1,日期物件轉成毫秒值。Date類中的getTime方法。
2,如何將獲取到的毫秒值轉成具體的日期呢?
Date類中的setTime方法。也可以通過建構函式。
*/
//日期物件轉成毫秒值
Date d = new Date();
long time1 = d.getTime();
long time2 = System.currentTimeMillis(); / /毫秒值。

//毫秒值轉成具體的日期
long time = 1322709921312l;
Date d = new Date();
d.setTime(time);
/*
將日期字串轉換成日期物件:使用的就是DateFormat方法中的 Date parse(String source) ;
*/
public static void method() throws Exception {
String str_time = “2011/10/25”;
DateFormat df = new SimpleDateFormat(“yyyy/MM/dd”); //SimpleDateFormat作為可以指定使用者自定義的格式來完成格式化。
Date d = df.parse(str_time);
}
/*
如果不需要使用特定的格式化風格,完全可以使用DateFormat類中的靜態工廠方法獲取具體的已經封裝好風格的物件。getDateInstance();getDateTimeInstance();
*/
Date d = new Date();
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
String str_time = df.format(d);

//將日期物件轉換成字串的方式:DateFormat類中的format方法。

//建立日期格式物件。

DateFormat df = new SimpleDateFormat(); //該物件的建立內部會封裝一個預設的日期格式。11-12-1 下午1:48
//如果想要自定義日期格式的話。可使用SimpleDateFormat的建構函式。將具體的格式作為引數傳入到建構函式中。如何表示日期中年的部分呢?可以必須要參與格式物件文件。
df = new SimpleDateFormat(“yyyy年MM月dd日 HH:mm:ss”);
//呼叫DateFormat中的format方法。對已有的日期物件進行格式化。

String str_time = df.format(d);

API— java.util. Calendar:日曆類
public static void method(){
Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.YEAR)+”年”+(c.get(Calendar.MONTH)+1)+”月”
+getNum(c.get(Calendar.DAY_OF_MONTH))+”日”
+”星期”+getWeek(c.get(Calendar.DAY_OF_WEEK)));
}
public static String getNum(int num){
return num>9 ? num+”” : “0”+num;
}
public static String getWeek(int index){
/*
查表法:建立資料的對應關係.
最好:資料個數是確定的,而且有對應關係。如果對應關係的一方,是數字,而且可以作為角標,那麼可以通過陣列來作為表。
*/
String[] weeks = {“”,”日”,”一”,”二”,”三”,”四”,”五”,”六”};
return weeks[index];

}

相關文章