您好,登錄后才能下訂單哦!
------- android培訓(xùn)、java培訓(xùn)、期待與您交流! ----------
1、集合類
為什么出現(xiàn)集合類?
面向?qū)ο笳Z言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,所以為了方便對(duì)多個(gè)對(duì)象的操作,就對(duì)對(duì)象進(jìn)行存儲(chǔ),集合就是存儲(chǔ)對(duì)象最常用的一 種方式。
數(shù)組和集合類同是容器,有何不同?
數(shù)組雖然也可以存儲(chǔ)對(duì)象,但長(zhǎng)度是固定的;集合長(zhǎng)度是可變的。數(shù)組中可以存儲(chǔ)基本數(shù)據(jù)類型,集合只能存儲(chǔ)對(duì)象。
集合類的特點(diǎn)
集合只用于存儲(chǔ)對(duì)象,集合長(zhǎng)度是可變的,集合可以存儲(chǔ)不同類型的對(duì)象。
2、集合框架的構(gòu)成及分類
3、Collection接口:
常用方法:
1,添加:
add(object):添加一個(gè)元素
addAll(Collection) :添加一個(gè)集合中的所有元素。
2,刪除:
clear():將集合中的元素全刪除,清空集合。
remove(obj) :刪除集合中指定的對(duì)象。注意:刪除成功,集合的長(zhǎng)度會(huì)改變。 removeAll(collection) :刪除部分元素。部分元素和傳入Collection一致。
3,判斷:
boolean contains(obj) :集合中是否包含指定元素。
boolean containsAll(Collection) :集合中是否包含指定的多個(gè)元素。 boolean isEmpty():集合中是否有元素。
4,獲?。?/p>
int size():集合中有幾個(gè)元素。
5,取交集:
boolean retainAll(Collection) :對(duì)當(dāng)前集合中保留和指定集合中的相同的元素。如果兩個(gè)集合元素相同,返回flase;如果retainAll修改了當(dāng)前集合,返回true。
6,獲取集合中所有元素:
Iterator iterator():迭代器
7,將集合變成數(shù)組:
toArray();
4、List接口:元素是有序的,元素可以重復(fù)。因?yàn)樵摷象w系有索引。
常用子類:
ArrayList:底層的數(shù)據(jù)結(jié)構(gòu)使用的是數(shù)組結(jié)構(gòu)。特點(diǎn):查詢速度很快。但是增刪稍慢。線程不同步。
練習(xí):
import java.util.*; import java.lang.*; /* 將自定義對(duì)象作為元素存到ArrayList集合中,并去除重復(fù)元素。 比如:存人對(duì)象。同姓名同年齡,視為同一個(gè)人。為重復(fù)元素。 思路: 1,對(duì)人描述,將數(shù)據(jù)封裝進(jìn)人對(duì)象。 2,定義容器,將人存入。 3,取出。 List判斷元素是否相同,依據(jù)的是元素的equals方法。 */ class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if (!(obj instanceof Person)) throw new RuntimeException("類型不匹配"); Person p = (Person)obj; System.out.println(this.name+"===="+p.name); return this.name.equals(p.name) && this.age == p.age; } public String getName() { return name; } public int getAge() { return age; } } class ArrayListTest2 { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add(new Person("zhangsan",34)); al.add(new Person("zhangsan",34)); al.add(new Person("lisi",32)); al.add(new Person("wangwu",24)); al.add(new Person("wangwu",24)); al.add(new Person("zhaoliu",23)); al = singleElement(al); for (Iterator it = al.iterator();it.hasNext() ; ) { Person p = (Person)it.next(); sop(p.getName()+","+p.getAge()); } } public static ArrayList singleElement(ArrayList al) { //定義一個(gè)臨時(shí)容器。 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while (it.hasNext()) { Object obj = it.next(); if (!newAl.contains(obj))//調(diào)用底層方法調(diào)用的是equals方法。所以需要復(fù)寫equals方法。 newAl.add(obj); } return newAl; } }
LinkedList:底層使用的是鏈表數(shù)據(jù)結(jié)構(gòu)。特點(diǎn):增刪速度很快,查詢稍慢。不同步。
相關(guān)練習(xí):
/* 使用LinkedList模擬一個(gè)堆?;蛘哧?duì)列數(shù)據(jù)結(jié)構(gòu)。 堆棧:先進(jìn)后出。如同一個(gè)杯子。 隊(duì)列:先進(jìn)先出。First in First out FIFO 如同一個(gè)水管。 */ import java.util.*; class DuiLie { private LinkedList link; DuiLie() { link = new LinkedList(); } public void myAdd(Object obj) { link.addFirst(obj); } public void myget() { return link.removeLast(); } public boolean isNull() { return link.isEmpty(); } }
Vector:底層是數(shù)組數(shù)據(jù)結(jié)構(gòu)。線程同步。被ArrayList替代了。
相關(guān)練習(xí):
import java.util.*; /* 枚舉就是Vector特有的取出方式。 發(fā)現(xiàn)枚舉和迭代器很像。 其實(shí)枚舉和迭代時(shí)一樣的。 為什么要設(shè)置枚舉? 因?yàn)槊杜e的名稱以及方法的名稱都過長(zhǎng)。 所以都被迭代器取代了。 枚舉郁郁而終。 */ class VectorDemo { public static void main(String[] args) { Vector v = new Vector(); v.add("java01"); v.add("java02"); v.add("java03"); v.add("java04"); Enumeration en = v.elements(); while (en.hasMoreElements()) { System.out.println(en.nextElement()); } } }
特有方法:
增:
add(index,element);在
addAll(index,Collection):
刪:
remove(index);
改:
set(index,element);
查:
get(index);
subList(form,to);
listIterator();
List集合特有的迭代器。ListIterator是Iterator的子接口。在迭代時(shí),不可以通過集合對(duì)象的方法操作集合中的元素。因?yàn)闀?huì)發(fā)生ConcurrentModificationException異常。所以,在迭代器時(shí),只能用迭代器的方法操作元素,可是Iterator方法時(shí)有限的。只能對(duì)元素進(jìn)行判斷,取出,刪除的操作。如果要其他操作如添加,修改等,就需要使用其子接口,ListIterator。該接口只能通過List集合的ListIterator方法獲取。
5、Set:元素是無序的,元素不可以重復(fù)。
|--HashSet:底層數(shù)據(jù)結(jié)構(gòu)是哈希表。線程非同步的。
HashSet是如何保證元素的唯一性的呢?
是通過元素的兩個(gè)方法,hashCode和equals來完成。
如果元素的HashCode值相同,才會(huì)判斷equals是否為true。
如果元素的hashCode值不同,不會(huì)調(diào)用equals。
注意:對(duì)于判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashCode和equals方法。
練習(xí):
/* 往HashSet集合中存入自定義對(duì)象。 姓名和年齡視為同一人。重復(fù)元素。 */ import java.util.*; class HashSetTest { public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1",11)); hs.add(new Person("a1",11)); hs.add(new Person("a2",13)); hs.add(new Person("a3",15)); //hs.add(new Person("a4",17)); sop("a1"+hs.contains(new Person("a2",13))); sop("a1"+hs.remove(new Person("a3",15))); for (Iterator it = hs.iterator();it.hasNext() ; ) { Person p = (Person)it.next(); sop(p.getName()+","+p.getAge()); } } } class Person { private String name; private int age; Person(String name,int age) { this.name = name; this.age = age; } public int hashCode() { return name.hashCode()+age; } public boolean equals(Object obj) { if (!(obj instanceof Person)) throw new RuntimeException("數(shù)據(jù)異常"); Person p = (Person)obj; return this.name.equals(p.name) && this.age == p.age; } public String getName() { return name; } public int getAge() { return age; } }
|--TreeSet:可以對(duì)Set集合中的元素進(jìn)行排序。
記?。号判驎r(shí),當(dāng)注意條件相同時(shí),一定要判斷一下次要條件。
因?yàn)?span id="uxr3qof" class="Apple-tab-span">底層數(shù)據(jù)結(jié)構(gòu)是二叉樹,保證元素唯一性的依據(jù):compareTo方法return 0;
TreeSet排序的第一種方式:讓元素自身具備比較性。元素需要實(shí)現(xiàn)Comparable接口,覆蓋compareTo方法。
TreeSet的第二種排序方式。當(dāng)元素自身不具備比較性時(shí),或者具備的比較性不是所需要的。這時(shí)就需要讓集合自身具備比較性。在集合初始化時(shí),就具備比較性。
練習(xí):
/* 練習(xí):按照字符串長(zhǎng)度排序。 字符串本身具備比較性,但是它的比較方式不是所需要的。 */ import java.util.*; class TreeSetTest { public static void main(String[] args) { TreeSet ts = new TreeSet(new StrLenCompare()); /*匿名內(nèi)部類。 TreeSet ts = new TreeSet(new Comparator(){ public int compare(Object o1,Object o2) { if (!(o1 instanceof String && o2 instanceof String)) throw new RuntimeException("類型不匹配"); String s1 = (String)o1; String s2 = (String)o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if (num==0) return s1.compareTo(s2); return num; } }); */ ts.add("abcd"); ts.add("cc"); ts.add("cba"); ts.add("aaa"); ts.add("z"); ts.add("hahaha"); for (Iterator it=ts.iterator();it.hasNext() ; ) { System.out.println(it.next()); } } } class StrLenCompare implements Comparator { public int compare(Object o1,Object o2) { if (!(o1 instanceof String && o2 instanceof String)) throw new RuntimeException("類型不匹配"); String s1 = (String)o1; String s2 = (String)o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); if (num==0) return s1.compareTo(s2); return num; } }
5、Map集合:
Map集合:該集合存儲(chǔ)鍵值對(duì)。是一對(duì)一對(duì)往里村,要保證鍵的唯一性。
1,添加。
V put(K key, V value)
void putAll(Map<? extends K,? extends V> m)
2,刪除。
void clear();
V remove(Object key)
3,判斷。
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
4,獲取。
V get(Object key)
int size()
Collection<V> values()
5、 重點(diǎn):
Set<Map.Entry<K,V>> entrySet()
Set<K> keySet()
常用Map子類:
|--Hashtable:底層是哈希表數(shù)據(jù)結(jié)構(gòu),不可以存入null鍵null值。該集合時(shí)線程同步的。JDK1.0,效率低
|--hashMap:底層是哈希表數(shù)據(jù)結(jié)構(gòu)。允許使用null鍵null值,該集合是不同步的。JDK1.2 效率高。
|--TreeMap:底層是二叉樹數(shù)據(jù)結(jié)構(gòu),線程不同步??梢杂糜诮omap集合中的鍵進(jìn)行排序。
Map和Set很像。
其實(shí)Set底層就是使用了Map集合。
map集合的兩種取出方式。
1,Set<Map.Entry<k,v>>entrySet:將map集合中的映射關(guān)系存入到了set集合中,而這個(gè)關(guān)系的數(shù)據(jù)類型就是Map.Entry。
2,Set<K> keySet:將map中所有的鍵存入到Set集合,因?yàn)镾et集合具備迭代器。所以可以迭代方式取出所有的鍵,在根據(jù)get方法。獲取每一個(gè)鍵對(duì)應(yīng)的值。Map集合的取出原理:將map集合轉(zhuǎn)成set集合,在通過迭代器取出。
例子:
import java.util.*; class MapDemo2 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("02","zhangsan02"); map.put("05","zhangsan05"); map.put("03","zhangsan03"); map.put("01","zhangsan01"); //將Map集合中的映射關(guān)系取出。存入到Set集合中。 Set<Map.Entry<String,String>> entrySet = map.entrySet(); for (Iterator<Map.Entry<String,String>> it = entrySet.iterator();it.hasNext() ; ) { Map.Entry<String,String> me = it.next(); String key = me.getKey(); String value = me.getValue(); System.out.println("key:"+key+"=value:"+value); } /* //先獲取map集合的所有鍵的set集合,keySet(); Set<String> keySet = map.keySet(); //有了Set集合,就可以獲取其迭代器。 Iterator<String> it = keySet.iterator(); while (it.hasNext()) { String key = it.next(); //有了鍵就可以通過map集合的get方法獲取其對(duì)應(yīng)的值。 String value = map.get(key); System.out.println("key:"+key+"=value:"+value); } */ } } /* Map.Entry 其實(shí)Entry也是一個(gè)接口,它是Map接口中的一個(gè)內(nèi)部接口。 */ interface Map { public static interface Entry { public abstract object getKey(); public abstract object getValue(); } }
6、常用工具類
Collections:它的出現(xiàn)給集合操作提供了更多的功能。這個(gè)類不需要?jiǎng)?chuàng)建對(duì)象,內(nèi)部提供的都是靜態(tài)方法。
靜態(tài)方法:
Collections.sort(list);//list集合進(jìn)行元素的自然順序排序。
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");//二分查找,返回角標(biāo)。
Collections.reverseOrder();//逆向反轉(zhuǎn)排序。
Collections.shuffle(list);//隨機(jī)對(duì)list中的元素進(jìn)行位置的置換。
將非同步集合轉(zhuǎn)成同步集合的方法:
Collections中的 XXX synchronizedXXX(XXX);
List synchronizedList(list);
Map synchronizedMap(map);
原理:定義一個(gè)類,將集合所有的方法加同一把鎖后返回。
Collection 和 Collections的區(qū)別:
Collections是個(gè)java.util下的類,是針對(duì)集合類的一個(gè)工具類,提供一系列靜態(tài)方法,實(shí)現(xiàn)對(duì)集合的查找、排序、替換、線程安全化(將非同步的集合轉(zhuǎn)換成同步的)等操作。
Collection是個(gè)java.util下的接口,它是各種集合結(jié)構(gòu)的父接口,繼承于它的接口主要有Set和List,提供了關(guān)于集合的一些操作,如插入、刪除、判斷一個(gè)元素是否其成員、遍歷等。
-------------------------------------------------------
Arrays:用于操作數(shù)組對(duì)象的工具類,里面都是靜態(tài)方法。
asList方法:將數(shù)組轉(zhuǎn)換成list集合。
String[] arr = {"abc","kk","qq"}
List<String> list = Arrays.asList(arr);//將arr數(shù)組轉(zhuǎn)成list集合。
將數(shù)組轉(zhuǎn)換成集合,有什么好處呢?用aslist方法,將數(shù)組變成集合;
可以通過list集合中的方法來操作數(shù)組中的元素:isEmpty()、contains、indexOf、set;
注意(局限性):數(shù)組是固定長(zhǎng)度,不可以使用集合對(duì)象增加或者刪除等,會(huì)改變數(shù)組長(zhǎng)度的功能方法。比如add、remove、clear。(會(huì)報(bào)不支持操作異常UnsupportedOperationException);
如果數(shù)組中存儲(chǔ)的引用數(shù)據(jù)類型,直接作為集合的元素可以直接用集合方法操作。
如果數(shù)組中存儲(chǔ)的是基本數(shù)據(jù)類型,asList會(huì)將數(shù)組實(shí)體作為集合元素存在。
集合變數(shù)組:用的是Collection接口中的方法:toArray();
如果給toArray傳遞的指定類型的數(shù)據(jù)長(zhǎng)度小于了集合的size,那么toArray方法,會(huì)自定再創(chuàng)建一個(gè)該類型的數(shù)據(jù),長(zhǎng)度為集合的size。
如果傳遞的指定的類型的數(shù)組的長(zhǎng)度大于了集合的size,那么toArray方法,就不會(huì)創(chuàng)建新數(shù)組,直接使用該數(shù)組即可,并將集合中的元素存儲(chǔ)到數(shù)組中,其他為存儲(chǔ)元素的位置默認(rèn)值null。
所以,在傳遞指定類型數(shù)組時(shí),最好的方式就是指定的長(zhǎng)度和size相等的數(shù)組。
將集合變成數(shù)組后有什么好處?限定了對(duì)集合中的元素進(jìn)行增刪操作,只要獲取這些元素即可。
--------------------------------------------------------------------
System類:
描述系統(tǒng)一些信息。
獲取系統(tǒng)屬性信息:Properties getProgerties();
out:標(biāo)準(zhǔn)輸出:默認(rèn)是控制臺(tái)。
in:標(biāo)準(zhǔn)輸入,默認(rèn)是鍵盤。
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
Properties prop =System.getProperties();
//因?yàn)镻roperties是Hashtable子類,也就是Map集合的一個(gè)子類對(duì)象。
//那么可以通過map的方法取出該集合中的元素。
//該集合中存儲(chǔ)的都是字符串,沒有泛型定義。
//如何在系統(tǒng)中自定義一些特有信息呢?
System.setProperty("mykey","myvalue");
//獲取指定屬性信息。
String value = System.getProperty("os.name");
System.out.println("value="+value);
//可不可以在jvm啟動(dòng)時(shí),動(dòng)態(tài)加載一些屬性信息呢?
//-D<name>=<value>
String v =System.getProperty("hah");
System.out.println("v="+v);
/*
for(Object obj:prop.keySet())
{
String value =(String)prop.get(obj);
System.out.println(obj+"="+value);
}
*/
}
}
-----------------------------------------------------------------------
Runtim對(duì)象
該類并沒有提供構(gòu)造函數(shù)。
說明不可以new對(duì)象。那么會(huì)直接想到該類的方法都是靜態(tài)的。
發(fā)現(xiàn)該類中還有非靜態(tài)方法。
說明該類肯定會(huì)提供了方法獲取本類對(duì)象,而且該方法是靜態(tài)的。并且返回值類型是本類類型。
由這個(gè)特點(diǎn)可以看出該類使用了單例設(shè)計(jì)模式完成。
該方法是static Runtime getRuntime();
*/
class RuntimeDemo
{
public static void main(String[] args) throws Exception
{
Runtime r = Runtime.getRuntime();
Process p = r.exec("notepad.exe SystemDemo.java");//\為轉(zhuǎn)義字符,所以應(yīng)寫為\\
//p.destroy();
}
}
------------------------------------------------------------------------
Date對(duì)象
可以對(duì)時(shí)間的進(jìn)行操作的對(duì)象。
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Date d = new Date();
System.out.println(d);
//將模式封裝到SimpleDateFormat對(duì)象中。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E kk:mm:ss");
//調(diào)用format方法,讓模式格式化指定Date對(duì)象。
System.out.println(sdf.format(d));
}
}
-----------------------------------------------------
Calendar對(duì)象
import java.util.*;
import java.text.*;
class CalendarDemo
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
String[] month = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[] week ={"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
int index = c.get(Calendar.MONTH);
int index1= c.get(Calendar.DAY_OF_WEEK);
sop(c.get(Calendar.YEAR)+"年");
//sop(c.get((Calendar.MONTH)+1)+"月");
sop(month[index]);
sop(c.get(Calendar.DAY_OF_MONTH)+"日");
sop((c.get(Calendar.DAY_OF_WEEK)));
sop(week[index1]);
/*
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
sdf.format(d)
System.out.println(d);
*/
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
------------------------------------------------------------------------
泛型(Generic)
泛型:JDK1.5版本以后出現(xiàn)的新特性。用于解決安全問題。是一個(gè)安全機(jī)制。
好處:
1,將運(yùn)行時(shí)期出現(xiàn)的問題ClassCastException,轉(zhuǎn)移到了編譯時(shí)期。
方便于程序員解決問題,讓運(yùn)行時(shí)期問題減少,安全。
2,避免了強(qiáng)制轉(zhuǎn)換的麻煩。
泛型格式:通過<>來定義要操作的引用數(shù)據(jù)類型。
在使用java提供的對(duì)象時(shí),什么時(shí)候?qū)懛盒湍兀?/p>
通常在集合框架中很常見。
只要見到<>就要定義泛型。
其實(shí)<>就是用了接受類型的。
當(dāng)使用集合時(shí),將集合中要存儲(chǔ)的數(shù)據(jù)類型作為參數(shù)傳遞到<>即可。
class GenericDemo { public static void main(String[] args) { ArrayList<String> al = new ArrayList<String>(); al.add("abc01"); al.add("abc02"); al.add("abc0991"); al.add("abc014"); //al.add(4); for (Iterator<String> it=al.iterator();it.hasNext() ; ) { String s = it.next(); System.out.println(s+":"+s.length()); } } }
泛型的使用
1、泛型類
在類聲明時(shí)通過一個(gè)標(biāo)識(shí)符表示類中某個(gè)字段的類型或者某個(gè)方法的返回值或參數(shù)的類型,這樣在類聲明或?qū)嵗臅r(shí)候只要指定自己需要的類型就ok。
聲明帶泛型的類:
class 類名<泛型類型1,泛型類型2……>{
泛型類型 變量名;
泛型類型 方法名(){}
返回值類型 方法名(泛型類型 變量名){}
}
使用帶泛型的類:
類名<具體類> 對(duì)象名 = new 類名<具體類>();
類型參數(shù)規(guī)范:推薦使用規(guī)范-常見的泛型,泛型只保存在源文件中,class文件中不存在;也就是說在編譯階段就會(huì)丟失,基本數(shù)據(jù)類型不能作為泛型類型;
K鍵,比如映射的鍵 key的類型
V值,比如Map的值 value類型
E元素,比如Set<E> Element表示元素,元素的類型
T 泛型,Type的意思
泛型好處:限定添加類型和消除強(qiáng)轉(zhuǎn)轉(zhuǎn)換的麻煩!
練習(xí)例子
需求:設(shè)計(jì)一個(gè)表示點(diǎn)的類Point,該類有兩個(gè)字段,一個(gè)是橫坐標(biāo)x,一個(gè)縱坐標(biāo)y,要求坐標(biāo)有3種表達(dá)形式(Integer,Double,String):
如果不使用泛型的話可以新建多個(gè)類,但是內(nèi)部方法體只有參數(shù)類型不一樣,所以用泛型的話更加簡(jiǎn)單,給定一個(gè)占位符,并不明確表示到底是什么類型,在實(shí)際運(yùn)用的時(shí)候才確定類型!!
很好的例子!
package generic;
class Point<T>{
private T t1;
private T t2;
public T getT1() {
return t1;
}
public void setT1(T t1) {
this.t1 = t1;
}
public T getT2() {
return t2;
}
public void setT2(T t2) {
this.t2 = t2;
}
}
public class GenericDemo {
public static void main(String[] args) {
//String 類型的
Point<String> p = new Point<String>();
p.setT1("2");
p.setT2("3");
System.out.println(p.getT1());
System.out.println(p.getT2());
//Integer 類型的
Point<Integer> p2 = new Point<Integer>();
p2.setT1(23);
p2.setT2(24);
System.out.println(p2.getT1());
System.out.println(p2.getT2());
//Double 類型的
Point<Double> p3 = new Point<Double>();
p3.setT1(23.00);
p3.setT2(24.00);
System.out.println(p3.getT1());
System.out.println(p3.getT2());
-----------------------------------------------------------------------------------------------------------------------------------------------
Set<String> s = new HashSet<String>();//創(chuàng)建一個(gè)容器對(duì)象,應(yīng)該在創(chuàng)建的時(shí)候就明確是裝什么的
s.add("a");
//s.add(1);//此時(shí)就加不進(jìn)去了,因?yàn)橐呀?jīng)限制了容器內(nèi)參數(shù)類型!
//此時(shí)就能保證集合里元素類型一致,
Set<Integer> treeSet = new TreeSet<Integer>();
//規(guī)定key只能是String,value是Date
Map<String,Date> map = new HashMap<String,Date>();
// V put(K key, V value)
Date v = map.put("", new Date());//和上面定義的類型一樣
//V get(Object key)
Date val = map.get("");
}
}
運(yùn)行結(jié)果
2
3
23
24
23.0
24.0
這樣的話借助泛型一個(gè)類就可以表達(dá)多個(gè)不同類型的參數(shù)!
要求
消除強(qiáng)制類型的轉(zhuǎn)換,如,使用Comparable比較時(shí)每次都需要類型強(qiáng)轉(zhuǎn);
1、沒有加上泛型,最初的需要強(qiáng)制類型轉(zhuǎn)換
package generic;
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable{//需要進(jìn)行排序的類要實(shí)現(xiàn)Comparable
private Integer age;
public Person(Integer age) {
super();
this.age = age;
}
@Override
public int compareTo(Object o) {
Person p = (Person)o;//強(qiáng)制類型轉(zhuǎn)換
return this.age.compareTo(p.age);
}
public String toString(){
return this.age.toString();
}
}
public class GenericDemo2 {
public static void main(String[] args) {
Set set = new TreeSet();
set.add(new Person(15));
set.add(new Person(12));
set.add(new Person(19));
set.add(new Person(53));
set.add(new Person(62));
System.out.println(set);
}
}
第二步:加上泛型,不再需要強(qiáng)轉(zhuǎn)(因?yàn)轭愋鸵呀?jīng)固定了)!
package generic;
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person>{//
private Integer age;
public Person(Integer age) {
super();
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age.compareTo(o.age);//排序
}
public String toString(){
return this.age.toString();
}
}
public class GenericDemo2 {
public static void main(String[] args) {
Set<Person> set = new TreeSet<Person>();
set.add(new Person(15));
set.add(new Person(12));
set.add(new Person(19));
set.add(new Person(53));
set.add(new Person(62));
System.out.println(set);
}
}
2、聲明多個(gè)泛型類型和通配符
若一個(gè)類中多個(gè)字段需要不同的泛型聲明,則在聲明類的時(shí)候指定多個(gè)泛型類型即可;
格式:
public interface IDAO<PK, T> {
PK add(T t);
void remove(PK id);
void update(PK id, T t);
T get(PK id);
}
在進(jìn)行引用傳遞的時(shí)候泛型類型必須匹配才可以傳遞,否則編譯不通過;
使用 ? ,表示未知類型的泛型對(duì)象:
List<?> 表示未知元素的List集合;
這種帶通配符的List僅表示各種泛型List的父類,并不能把元素添加入集合中;
List<?> list = new ArrayList<>(); list.add(1);//ERROR
public void show(List<?> list){}
//表示可接受任意類型的List集合
3、泛型的上限與下限
設(shè)置泛型對(duì)象的上限使用extends,表示參數(shù)類型只能是該類型或該類型的子類:
聲明對(duì)象:類名<? extends 類> 對(duì)象名
定義類:類名<泛型標(biāo)簽 extends 類>{}
設(shè)置泛型對(duì)象的下限使用super,表示參數(shù)類型只能是該類型或該類型的父類:
聲明對(duì)象:類名<? super 類> 對(duì)象名稱
定義類:類名<泛型標(biāo)簽 extends類>{}
public static void show(List<? extends Number> l){
}
public static void show(List<? super String> l){
}
public static void show(List<? extends Number> l){}
public static void show(List<? super String> l){}
泛型的上限
public static void main(String[] args) {
Person<Integer> p1 = new Person<>();
p1.setVal(99);
Person<Double> p2 = new Person<>();
p2.setVal(3.14);
Person<String> p3 = new Person<>();
p3.setVal("007");
show(p1);//√
show(p2);//√
show(p3);//×
}
public static void show(Person<? extends Number> p){//此處限定了Person的參數(shù)類型只能是Number或者是其子類,而String并不屬于Number。
System.out.println(p.getVal());
}
泛型的下限
public static void main(String[] args) {
Person<Integer> p1 = new Person<>();
p1.setVal(99);//Integer
Person<Double> p2 = new Person<>();
p2.setVal(3.14);//Double
Person<String> p3 = new Person<>();
p3.setVal("007");//String
Person<Object> p4 = new Person<>();
p4.setVal(new Object());//Object
show(p1);//×
show(p2);//×
show(p3);//√
show(p4);//√
}
public static void show(Person<? super String> p){
System.out.println(p.getVal());
}
很好的例子!
package generic;
import java.util.ArrayList;
import java.util.List;
public class GenericDemo3 {
public static void main(String[] args) {
//因?yàn)閟how方法是用List<?>通配符接收的,所以可以是任意類型!
List<String> l1 = new ArrayList<>();//new ArrayList<String>()
show(l1);
List<Double> l2 = new ArrayList<>();
show(l2);
List<Number> l3 = new ArrayList<>();
show(l3);
List<Object> l4 = new ArrayList<>();
show(l4);
//使用up方法的話接收類型為Number或者其子類
//up(l1);//錯(cuò)誤,因?yàn)閡p方法接收類型為Number或者其子類,l1(String)不符合!
up(l2);
up(l3);
//使用down方法的話接收類型為Number或者其父類
//down(l2);error
down(l3);
down(l4);
}
public static void down(List<? super Number> l){
for (Object object : l) {
System.out.println(object);
}
}
public static void up(List<? extends Number> l){
for (Object object : l) {
System.out.println(object);
}
}
public static void show(List<?> l){
for (Object object : l) {
System.out.println(object);
}
}
}
4、泛型接口和方法
java5后,可以聲明泛型接口,聲明方式和聲明泛型類是一樣的。
public interface IDAO<T>{}
泛型接口子類有兩種方式:
直接在子類后申明泛型;
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。