一、集合框架
爲什麼會出現這麼多的容器呢?
因爲每一個容器對數據的存儲方式都有不同。
這個存儲方式稱之爲:數據結構
Collection 也可以稱之爲單列集合
|--List:元素是有序的。輸入的元素可以重複,因爲該結合體繫有索引
|--ArrayList:底層的數據結構使用的是數組結構。特點:查詢速度快。但是增刪稍慢,線程不同步
|--LinkedList:底層的數據結構是鏈表數據結構。特點。增刪速度快。但是查詢速度慢,
|--Vector:底層的數據結構是數組結構。 線程同步。但是被ArrayList替代了。
枚舉是Vector特有的取出方式。
發現枚舉和迭代器很像
其實枚舉和迭代器是一樣的。
因爲枚舉的名稱以及方法的名稱都過長
所以被迭代器去取代了
而枚舉就鬱鬱而終
示例代碼
import java.util.Vector;
import java.util.Enumeration;
class VectorDemo
{
public static void main(String[] args)
{
Vector v = new Vector();
v.add("java01");
v.add("java02");
v.add("java03");
//使用枚舉遍歷集合中的元素
Enumeration e = v.elements();
for( ; e.hasMoreElements(); )
{
System.out.println(e.nextElement());
}
}
}
|--Set:該集合元素是無序的。輸入的元素不可以重複。因爲該體系中沒有索引
|--HashSet:底層數據結構是哈希表 線程是非同步的
HsshSet是如何保證元素唯一性的呢?
是通過元素的兩個方法,hashCode和equals來完成。
如果元素的HashCode的值相同,,纔會判斷equals是否爲true。
如果原數的HashCode的值不同,纔會調用equals
TreeSet的第二種排序方式。
當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時就需要讓集合自身具備比較性。
在集合初始化時,就有了比較性。
當兩種排序都存在時,一比較器爲主。
注意,對於判斷元素是否存在,以及刪除等操作,依賴的方法元素的hashCode和equals方法
import java.util.HashSet;
import java.util.Iterator;
class HashSetDemo
{
public static void main(String[] args)
{
//創建一個容器
HashSet hs = new HashSet();
hs.add("java01");
hs.add("java02");
hs.add("java02");
hs.add("java02");
//創建一個迭代器
Iterator it = hs.iterator();
for( ; it.hasNext(); )
{
System.out.println(it.next()); //結果爲java02 java01
}
}
}
|--TreeSet:可以對set集合中的元素進行排序。排序規則是參照英文字母的自然排序
底層結構是二叉樹,保證元素唯一性的依據;compareTo方法return 0代表元素相同
TreeSet排序的第一種方式:讓元素自身具備比較性。
元素需要實現Comparable接口,覆蓋compareTo方法
這種方式也稱爲元素的自然排序,或者叫做默認排序
示例:
需求:往TreeSet集合中存儲自定義對象學生。
想按照學的年齡就行排序。
記住了,排序時,當主要條件相同時,一定判斷一下次要條件
import java.util.TreeSet;
import java.lang.Comparable;
import java.util.Iterator;
class TreeSetTest
{
public static void main(String[] args)
{
//創建一個容器
TreeSet ts = new TreeSet();
ts.add(new Students("張三", 23));
ts.add(new Students("李四", 32));
s.add(new Students("王五", 23));
//創建一個迭代器
Iterator it = ts.iterator(); //只要容器中有元素。it.hasNext()結果永遠爲真。程序就能運行下去。一旦爲false。就停止
for( ; it.hasNext(); )
{
Students s = (Students)it.next(); //因爲it.next()是父類印象指向子類對象。所以在這裏要做強轉
System.out.println(s.getName() + "," + s.getAge());
}
}
}
//寫一個學生類
class Students implements Comparable //實現Comparable接口。對學生對象進行自定義排序
{
private String name;
private int age;
Students(String name, int age)
{
this.name = name;
this.age = age;
}
//重寫Comparable接口的方法
public int compareTo(Object obj)
{
if(!(obj instanceof Students)) //判斷一下是否是學生對象
throw new RuntimeException("對象不是學生對象");
Students s = (Students)obj;
if(this.age > s.age) //假如傳進來的對象年齡小於原來的對象年齡。就返回1
return 1;
if(this.age == s.age)
{
return this.name.compareTo(s.name); //如果年齡一樣的話。就比較名字。讓名字按照英文字母的順序排列
}
return -1;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
}
Set集合的功能和Collection是一致的
二、Collection的基本應用。和迭代器的基本使用
import java.util.ArrayList;
import java.util.Iterator;
/*
1,add方法的參數是Object.以便於接收任意類型對象。
2集合中存儲的都是對象的引用(也就是地址)
常用函數
add(); 添加元素
size(); 求集合的長度
contains(String); 判斷String字符是否存在於集合中
isEmpty(); 此函數判斷集合是否爲空
remove(String) 刪除數組中的Sring元素
clear(); 清空集合
retainAll() 去交集
remove() 刪除有交集的元素
什麼是迭代器?
其實就是集合的取出元素的方式。
把取出方式定義在集合的內部,
這樣取出方式就可以直接訪問集合內容的元素。
那麼取出方式就被定義成了內部類。
而每一個容器的數據結構不同。
所以取出的動作細節也不一樣,但是都有共性內容。
判讀和取出。那麼可以可以將共性抽取。
所以這些內部類都符合一個規則。該規則就是Iterator.
如何取出集合的取出對象呢?
通過一個對外提供的方法iterator();
*/
class CollectionDemo
{
public static void main(String[] args)
{
//mothed_1();
//mothed_2();
dieDai();
}
//結合容器Collection的一個基本應用
public static void mothed_1()
{
//創建一個集合容器,使用Collection接口的子類。ArrayList
ArrayList a1 = new ArrayList();
//添加元素
a1.add("java01");
a1.add("java02");
a1.add("java03");
a1.add("java04");
//獲取個數。求集合的長度
p("長度是:" + a1.size());
//打印集合
p("原集合:" + a1);
//判斷java03元素是否存在 運用contains函數
p("java03是否存在於集合中:" + a1.contains("java03"));
//判斷集合是否爲空 運用isEmpty()函數
p("判斷集合是否爲空:" + a1.isEmpty());
//刪除集合
a1.remove("java03"); //調用remove函數刪除集合中的元素
p("刪除單個元素後的集合:" + a1);
a1.clear(); //調用clear清空集合
p("清空後的集合:" + a1);
}
//集合中的交集小例子
public static void mothed_2()
{
//創建一個集合容器,使用Collection接口的子類。ArrayList
ArrayList a1 = new ArrayList();
//添加元素
a1.add("java01");
a1.add("java02");
a1.add("java03");
a1.add("java04");
ArrayList a2 = new ArrayList();
//添加元素
a2.add("java01");
a2.add("java02");
a2.add("java05");
a2.add("java06");
//a1.retainAll(a2); //判斷兩個容器是否有交集的地方,有的話。把交集的內容打印,.可以剪短的稱之爲取交集
//p(a1);
a1.removeAll(a2); //幹掉相同的元素
p(a1);
}
//簡單應用迭代器
public static void dieDai()
{
ArrayList s = new ArrayList();
s.add("java01");
s.add("java02");
s.add("java03");
s.add("java04");
/* 此爲while循環
//獲取迭代器 使用迭代器取出集合中的元素
Iterator it = s.iterator();
while(it.hasNext()) //判斷集合中是否有內容。有就往下執行
{
p(it.next()); //打印輸出集合中的內容
}
*/
//使用for循環使用迭代器
for(Iterator it = s.iterator(); it.hasNext(); )
{
p(it.next());
}
}
public static void p(Object obj)
{
System.out.println(obj);
}
}
二、List接口的使用
import java.util.ArrayList;
import java.util.ListIterator;
List
特有方法、凡是可以操作角標的方法都是該體系特有的方法
1、增加
add(index,element); 在角標爲index的位置上插入element元素
addAll(index,Collection); 在角標位置爲index的位置上插入一組元素
2、刪除
remove(index); 刪除角標位置爲index上的元素
3、修改
set(index,element); 修改角標位置爲index上的元素
4、查找
get(index); 查找角標位置爲index上的元素
subList(from,to); 查找角標位置從from到to但並不包含to的一組元素
listIterator();
List集合特有的迭代器,ListIterator是Iterator的子接口。
在迭代時,不可以通過集合對象的方法操作集合中的元素。
因爲會發生ConcurrentModificationException(併發修改異常)
所以,在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的。
只能對元素進行判斷,取出,刪除的操作,
如果想要其他操作如添加。修改等,就需要使用其子接口,ListIterator;
該接口只能通過list集合的listIterator方法獲取。
class ListDemo
{
public static void main(String[] args)
{
//list();
list_1();
}
//List的簡答應用
public static void list()
{
//創建一個集合容器,使用Collection的子類ArrayList
ArrayList s = new ArrayList();
//添加元素
s.add("java01");
s.add("java02");
s.add("java03");
p("添加前:" + s);
//增加元素
s.add(2,"java05"); //在角標位爲2的位置插入元素
p("添加後:" + s);
s.remove(3); //刪除角標位爲3的元素
p("刪除後:" + s);
s.set(2, "java08"); //把角標位爲2的元素修改成java08
p("修改後:" + s);
p("查找的單個元素是:" + s.get(2)); //查找角標位爲2的數組上的元素
p("查找到的多個元素:" + s.subList(0,3)); //以爲此方法查找包含頭,不包含尾。所以要查找到到所有元素。必須要比元素個數大1
}
//ListIterator的簡單應用
public static void list_1()
{
ArrayList s = new ArrayList();
s.add("java01");
s.add("java02");
s.add("java03");
ListIterator li = s.listIterator();
//使用List特有的迭代器ListIterator
for(; li.hasNext(); )
{
Object obj = li.next(); //子類對象指向父類引用
if(obj.equals("java03"))
{
li.set("java---3"); //對迭代器中的元素進行修改
li.add("java-----3"); //對迭代器中的元素進行添加
}
}
p("從頭往後遍歷:" + s);
for(; li.hasPrevious(); )
{
p(li.previous()); //從後往前遍歷
}
}
public static void p(Object obj)
{
System.out.println(obj);
}
}
三、類LinkedList的簡單應用
import java.util.LinkedList;
/*
LinkedLIST:特有方法
addFirst(); 每次都把元素添加在第一位
addLast(); 每一次都把元素添加到最後一位
//獲取元素,但是並不刪除元素。如果集合中沒有元素,會出現NoSuchEmelemtException異常
getFirst(); 獲取最前面的一位元素
getLast(); 獲取最後面的一位元素
//獲取元素,但是元素被刪除。如果集合中沒有元素,會出現NoSuchEmelemtException異常
removeFirst(); 刪除最前面的一位元素
removeLast(); 刪除最後面的一位元素
在jdk1.6中出現了替代的方法。
offerFirst(); 每次都把元素添加在第一位
offerLast(); 每一次都把元素添加到最後一位
//獲取元素,但是並不刪除元素。如果集合中沒有元素,會出現null;
peekFirst(); 獲取最前面的一位元素
peekLast(); 獲取最後面的一位元素
//獲取元素,但是元素被刪除。如果集合中沒有元素,會出現null;
pollFirst(); 刪除最前面的一位元素
pollLast(); 刪除最後面的一位元素
*/
class LinkedListDemo
{
public static void main(String[] args)
{
//mothed();
mothed_1();
}
//寫一個1.6以後出現的新特性的應用函數
public static void mothed_1()
{
//創建一個集合
LinkedList l = new LinkedList();
l.offerFirst("java02"); //addFirst();每次輸入進去的元素都放在第一位。把原來第一位上的元素擠到後面去
l.offerFirst("java01"); //所以結果爲:[java01, java02]
p(l);
l.offerLast("java03"); //addLast();每次輸入的元素都放在最後一位。並把原來排在最後一位的元素往前擠
l.offerLast("java04"); //所以結果爲:[java01, java02, java03, java04]
p(l);
//獲取第一個元素和最後一個元素
p("第一個元素是:" + l.peekFirst());
p("最後一個元素是:" + l.peekLast());
//刪除第一個元素
l.pollFirst();
p(l);
//刪除最後一個元素
l.pollLast();
p(l);
}
//寫一個LinkedList類的應用函數
public static void mothed()
{
//創建一個集合
LinkedList l = new LinkedList();
l.addFirst("java01"); //addFirst();每次輸入進去的元素都放在第一位。把原來第一位上的元素擠到後面去
l.addFirst("java02"); //所以輸出結果是:[java04, java03, java02, java01]
l.addFirst("java03");
l.addFirst("java04");
p(l);
l.addLast("java05"); //addLast();每次輸入的元素都放在最後一位。並把原來排在最後一位的元素往前擠
l.addLast("java06"); //所以輸出的結果是:[java04, java03, java02, java01, java05, java06, java07, java08]
l.addLast("java07");
l.addLast("java08");
p(l);
p("最前面的元素是:" + l.getFirst());
p("最後面的元素是:" + l.getLast());
l.removeFirst();
p(l); //刪除最前面的元素。結果爲:[java03, java02, java01, java05, java06, java07, java08]
l.removeLast();
p(l); //刪除最後面的元素。結果爲:[java03, java02, java01, java05, java06, java07]
}
public static void p(Object obj)
{
System.out.println(obj);
}
}
四、堆棧與隊列
/*
使用LinkedList模擬出一個堆棧或者隊列的數據結構
堆棧:先進後出
隊列:先進先出
*/
import java.util.LinkedList;
//寫一個對列
class DuiLie
{
private LinkedList ll;
DuiLie()
{
ll = new LinkedList();
}
//輸入元素
public void myAdd(Object obj)
{
ll.addFirst(obj); //把每次傳進來的元素都放在第一位
}
//獲取元素
public Object myGet()
{
return ll.removeLast(); //把要刪除的元素反出去。這樣可以保證把存進來元素一次取出
}
//添加一個判斷是否存在元素的函數
public boolean isNull()
{
return ll.isEmpty();
}
}
//寫一個堆棧
class DuiZhan
{
private LinkedList ll;
DuiZhan()
{
ll = new LinkedList();
}
//輸入元素
public void myAdd(Object obj)
{
ll.addFirst(obj);
}
//獲取元素
public Object myGet()
{
return ll.removeFirst();
}
//判斷是否爲空
public boolean isNull()
{
return ll.isEmpty();
}
}
class LinkedListTest
{
public static void main(String[] args)
{
//調用堆棧
duiZhan();
//調用隊列
duiLie();
}
//寫一個應用堆棧的函數
public static void duiZhan()
{
DuiZhan d = new DuiZhan(); //創建一個容器
d.myAdd("java03"); //輸入元素
d.myAdd("java04");
//獲取全部元素
for( ; !d.isNull(); )
{
p(d.myGet());
}
}
//寫一個應用隊列的函數
public static void duiLie()
{
DuiLie d = new DuiLie();
d.myAdd("java01"); //添加元素
d.myAdd("java02");
//獲取全部元素
for( ; !d.isNull(); )
{
p(d.myGet());
}
}
public static void p(Object obj)
{
System.out.println(obj);
}
}
五、泛型:JDK1.5版本以後出現新特性,用於解決安全問題,是一個類型安全機制。
一、泛型
泛型的好處:
1,將運行時期出現問題ClassCastException(類型轉換異常)轉移到了編譯時期,
方便與程序員解決問題,讓運行時期問題減少,安全。
2,避免了強制轉換麻煩。
//定義一個只能裝String類型的數據的容器
ArrayList<String> al = new ArrayList<String>();
al.add("java");
al.add("jaasdfds");
al.add("adfasf");
Iterator<String> it = al.iterator(); //建立一個String類型的迭代器
for( ; it.hasNext(); )
{
String s = it.next();
System.out.println(s + " " + s.length());
}
泛型的格式:通過<>來定義要操作的引用數據類型。
在使用java提供的對象時,什麼時候寫泛型呢?
通常在集合框架中很常見。
只要見到<>就要定義泛型。
其實<>就是用來接收類型的。
當使用集合時,將集合中要存儲的數據類型作爲參數傳遞到<>即可。
示例代碼:
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
class GenericDemo
{
public static void main(String[] args)
{
TreeSet<String> ts = new TreeSet<String>(new LenBi()); //創建一個String類型的容器
ts.add("abd");
ts.add("bc");
ts.add("g");
ts.add("ddd");
ts.add("agdg");
Iterator<String> it = ts.iterator(); //創建一個String類型的迭代器
for( ; it.hasNext(); )
{
String s = it.next(); //把遍歷的元素賦值給變量s;
System.out.println(s + " " + s.length());
}
}
}
//定義一個比較長度的比較器
class LenBi implements Comparator<String> //定義一個判斷字符串長度的比較器
{
public int compare(String s1, String s2)
{
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num == 0)
{
return s1.compareTo(s2);
}
return num;
}
}
六、泛型類
/*
泛型類
什麼時候定義泛型呢:
當類中要操作的引用數據類型不確定的時候,
早期定義Object來完成擴展。
現在定義泛型來完成擴展。
*/
class Worker
{
}
//沒有泛型之前的做法
class SetObject
{
private Object obj;
public void setObject(Object obj)
{
this.obj = obj;
}
public Object getObject()
{
return obj;
}
}
//寫一個泛型類
class FanXing<QQ>
{
private QQ q;
public void setQQ(QQ q)
{
this.q = q;
}
public QQ getQQ()
{
return q;
}
}
class GenericDemo1
{
public static void main(String[] args)
{
SetObject s = new SetObject();
s.setObject(new Worker());
Worker w = (Worker)s.getObject();
//運用泛型
FanXing<Worker> f = new FanXing<Worker>();
f.setQQ(new Worker());
Worker w1 = f.getQQ();
}
}
七、泛型限定
?通配符。也可以理解爲佔位符。
泛型的限定:
? extends E: 可以接收E類型或者E的子類型。上限
? super E: 可以接收E類型或者E的父類型。下限
示例代碼:
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
class GenericSuper
{
public static void main(String[] args)
{
//創建一個容器。只打印狗類
TreeSet<Dog> d = new TreeSet<Dog>(new Comp());
d.add(new Dog("小狗"));
d.add(new Dog("老狗")); //給容器添加元素
d.add(new Dog("中型狗"));
//創建一個容納貓類的容器
TreeSet<Cat> c = new TreeSet<Cat>(new Comp());
c.add(new Cat("小貓"));
c.add(new Cat("老貓")); //給容器添加元素
c.add(new Cat("中年貓"));
daYin(d); //調用函數打印元素
daYin(c);
}
public static void daYin(TreeSet<? extends Animal> ts) //使用上限的方式對兩個容器元素進行輸出
{
Iterator<? extends Animal> it = ts.iterator();
for( ; it.hasNext(); )
{
System.out.println(it.next().getName());
}
}
}
class Comp implements Comparator<Animal> //使用下限的形式創建了一個比較器
{
public int compare(Animal a1, Animal a2)
{
return a1.getName().compareTo(a2.getName()); //按照自然順序把名字排列
}
}
//創建一個動物類
class Animal
{
private String name; //定義動物名字變量
Animal(String name) //定義構造函數。讓其在建立對象的時候就設置好名字
{
this.name = name;
}
//設置名字
public void setName(String name)
{
this.name = name;
}
//返回名字
public String getName()
{
return name;
}
}
//創建一個狗類
class Dog extends Animal
{
Dog(String name)
{
super(name);
}
}
//創建一個貓類
class Cat extends Animal
{
Cat(String name)
{
super(name);
}
}
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Unity開發</a>、<a href="http://edu.csdn.net"target="blank">.Net培訓</a>、期待與您交流! ----------------------
詳細請查看:<a href="http://edu.csdn.net" target="blank">http://edu.csdn.net</a>