API-集合框架-Collection

 
 
一、集合體系概述
 
1、爲什麼出現集合類?
面嚮對象語言對事物的體現都是以對象的形式,所以爲了方便對多個對象的操作,就對對象進行存儲,集合就是存儲對象最常用的一種方式。
 
2、數組和集合類同是容器,有何不同?
數組雖然也可以存儲對象,但長度是固定的;集合長度是可變的。數組中可以存儲基本數據類型,集合只能存儲對象。
集合只用於存儲對象,集合長度是可變的,集合可以存儲不同類型的對象。
 
3、集合類的特點
集合中存儲的都是對象的引用(地址)。
 
4、集合框架 
爲什麼會出現這麼多容器?
因爲每一個容器對數據的存儲方式不同。存儲方式稱之爲:數據結構
 
Collection是集合框架中的根接口。其下有兩個常用子接口:List(列表),Set(集)。
所屬關係:Collection

 

                         |--List  //元素是有序的,元素可以重複。因爲該集合體繫有索引。

 

                         |--Set  //元素是無序的,元素不可以重複。
 
 
二、Collection的共性方法
 
1、添加元素
        add(Object obj); //add方法的參數類型是Object。以便於接收任意類型對象。

2、獲取個數,集合長度
        size();
 
3、刪除元素
        remove(Object obj);
        clear();//清空集合

4、判斷元素
        contains(Object obj);//判斷是否存在obj這個元素
        isEmpty();//是否爲空

5、取交集
        retainAll(另一集合);//調用者只保留兩集合的共性元素。
 
6、獲取元素
        迭代器:Iterator--其實就是集合的取出元素的方式。
        方法:hasNext();//如果仍有元素可以迭代,返回true。
                   next();//返回迭代的下一個元素。
                   remove();//移除最後一個元素。
        方式一:  Iterator it = al2.iterator();//獲取迭代器,用於取出集合中的元素。         while (it.hasNext())         {     sop("al2:"+it.next());         }
方式二: for (Iterator it = al2.iterator(); it.hasNext(); )
        {
    sop("al2:"+it.next());
        }
        注意:在迭代式循環中next調用一次,就要hasNext判斷一次。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
1,add方法的參數類型是Object。以便於接收任意類型對象。
2,集合中存儲的都是對象的引用(地址)。
3,迭代器:其實就是集合的取出元素的方式。
*/
classCollectionDemo
{
publicstaticvoid main(String[] args)
{
//創建一個集合容器。使用Collection接口的子類。ArrayList
ArrayList al1 =newArrayList();
ArrayList al2 =newArrayList();
 
//1、添加元素。
		al1.add("java01");//add(Object obj);
		al1.add("java02");
		al1.add("java03");
		al1.add("java04");
 
		al2.add("java01");//add(Object obj);
		al2.add("java02");
		al2.add("java05");
		al2.add("java06");
 
 
//打印集合
		sop("原集合al1:"+al1);
 
//2、獲取個數。集合長度。
		sop("al1:size = "+al1.size());
 
//3、刪除元素
		al1.remove("java03");
 
//al.clear();//清空集合。
		sop("新集合al1:"+al1);
 
//4、判斷元素。
		sop("java01是否存在於al1:"+al1.contains("java01"));
		sop("al1集合是否爲空:"+al1.isEmpty());
 
//5、取交集。al1中只會保留al2中相同的元素。
		al1.retainAll(al2);
//al1.removeAll(al2);
		sop("al2"+al2);
		sop("al1與al2取交集後的al1:"+al1);
 
//獲取元素
Iterator it = al2.iterator();//獲取迭代器,用於取出集合中的元素。
while(it.hasNext())
{
			sop("al2:"+it.next());
}
/*for (Iterator it = al2.iterator(); it.hasNext(); )
		{
			sop("al2:"+it.next());
		}*/
}
 
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
運行結果:
 
 
三、List
 
1、 List:元素是有序的,元素可以重複。因爲該集合體繫有索引。
         |--ArrayList:底層的數據結構使用的是數組結構。特點:查詢速度很快。但是增刪稍慢。線程不同步。
         |--LinkedList:底層使用的是鏈表數據結構。特點:增刪速度很快,查詢稍慢。
         |--Vector:底層是數組數據結構。線程同步。被ArrayList替代了。
 
2、List特有方法:凡是可以操作角標的方法都是該體系特有的方法。
a.增:add(index,element);
b.刪:remove(index);
c.改:set(index,element);
d.查:get(index);
          subList(from,to);
          listIterator();
ListIterator:List集合特有的迭代器,是Iterator的子接口    
ListIterator特有的方法:
        add(obj);//增加
        set(obj);//修改爲obj
        hasPrevious();//判斷前面有沒有元素
        previous();//取前一個元素
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">/*
Collection
     |--List:元素是有序的,元素可以重複。因爲該集合體繫有索引。
	 |--Set:元素是無序的,元素不可以重複。因爲該集合體系沒有索引。
List:
特有方法:凡是可以操作角標的方法都是該體系特有的方法。
 
增:add(index,element);
   add(index,Collection);
 
刪:remove(index);
 
改:set(index,element);
 
查:get(index);
   subList(from,to);
   listIterator();
 
List集合特有的迭代器:ListIterator是Iterator的子接口
ListIterator特有的方法:
        add(obj);//增加
        set(obj);//修改
        hasPrevious();//判斷前面有沒有元素
        previous();//取前一個元素
*/
import java.util.*;
classListDemo
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
//添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java03");
 
//打印集合
		sop("原集合al:"+al);
 
//在指定位置添加元素
		al.add(1,"java08");
		sop("在指定位置1添加元素:"+al);
 
//刪除指定位置元素
		al.remove(2);
		sop("刪除指定位置2元素:"+al);
 
//修改指定位置元素。
		al.set(2,"java05");
		sop("修改指定位置2元素:"+al);
 
//通過角標獲取元素
		sop("通過角標獲取元素get(1):"+al.get(1));
 
//通過角標遍歷所有元素
		sop("遍歷獲取所有元素:");
for(int x=0; x<al.size(); x++)
{
			sop("al("+x+")="+al.get(x));
}
//通過indexOf獲取對象的位置
		sop("index="+al.indexOf("java05"));
 
//返回子列表
List sub  = al.subList(1,3);
		sop("sub="+sub);
 
//演示列表迭代器
Iterator it = al.iterator();
while(it.hasNext())
{
//sop("al:"+it.next());
Object obj = it.next();
if(obj.equals("java01"))
//al.add("java009");//發生ConcurrentModificationException異常。
				it.remove();//Iterator方法有限,只有hasNext(); next(); remove();方法
}
		sop(al);
//如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。該接口只能通過List集合的ListIterator方法獲取。
ListIterator li = al.listIterator();
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java05"))
				li.add("java09");//添加
}
		sop(al);
while(li.hasPrevious())//向前逆向遍歷
{
Object obj = li.previous();//取前一個元素
if(obj.equals("java09"))
				li.set("java0007");//修改
}
		sop(al);
 
 
}
 
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
運行結果:
 
3、ArrayList
ArrayList:底層的數據結構使用的是數組結構。特點:查詢速度很快。但是增刪稍慢。線程不同步。
例:去除ArrayList集合中的重複元素。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
去除ArrayListTest集合中的重複元素
*/
classArrayListTest
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
//添加元素。
		al.add("java01");//add(Object obj);
		al.add("java02");
		al.add("java02");
		al.add("java03");
		al.add("java03");
		sop(al);
		al = singleElement(al);
		sop(al);
}
 
publicstaticArrayList singleElement(ArrayList al)
{
//定義一個臨時容器
ArrayList newAl =newArrayList();
 
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
				newAl.add(obj);
}
}
return newAl;
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
運行結果:
 
例:將自定義對象作爲元素存到ArrayList集合中,並去除重複元素。如存人對象,同姓名同年齡視爲同一個人。
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
將自定義對象作爲元素存到ArrayList集合中,並去除重複元素。如存人對象,同姓名同年齡視爲同一個人
List集合判斷元素是否相同,依據是元素的equals方法。
contains 底層調用的是equals方法,所以要重寫equals方法。
*/
 
classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicboolean equals(Object obj)
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
//System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classArrayListTest1
{
publicstaticvoid main(String[] args)
{
ArrayList al =newArrayList();
 
		al.add(newPerson("lisi01",11));//al.add(Object obj);//Object obj = new Person("lisi01",11);
		al.add(newPerson("lisi02",12));
		al.add(newPerson("lisi02",12));
		al.add(newPerson("lisi03",13));
		al.add(newPerson("lisi04",14));
		al.add(newPerson("lisi04",14));
		sop("原ArrayList集合:");
		printAl(al);
		al = singleElement(al);
		sop("新ArrayList集合:");
		printAl(al);
}
 
publicstaticvoid printAl(ArrayList al)
{
Iterator it = al.iterator();
while(it.hasNext())
{
//Object obj = it.next();  
Person p =(Person)it.next();
				sop(p.getName()+"::"+p.getAge());
}
}
 
publicstaticArrayList singleElement(ArrayList al)
{
//定義一個臨時容器
ArrayList newAl =newArrayList();
 
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))
{
				newAl.add(obj);
}
}
return newAl;
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
運行結果:
 
4、LinkedList
LinkedList:底層使用的是鏈表數據結構。特點:增刪速度很快,查詢稍慢。
LinkedList特有方法:
                                                                      在JDK1.6以後,出現了替代方法。
addFirst();                                                        offFirst();
addLast();                                                        offLast();
 
getFirst();                                                         peekFirst();
getLast();                                                         peekLast();
獲取元素,但不刪除元素。                              獲取元素,但不刪除元素。
如果集合中沒有元素,                                     如果集合中沒有元素,
會出現NoSuchElementException。              會返回null。
 
removeFirst();                                                  pollFirst();
removeLast();                                                  pollLast();
獲取元素,並刪除元素。                                  獲取元素,並刪除元素。 
如果集合中沒有元素                                         如果集合中沒有元素,
會出現NoSuchElementException。               會返回null。
例:  使用LinkedList模擬一個堆棧或者隊列數據結構。
 
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
使用LinkedList模擬一個堆棧或者隊列數據結構。 
堆棧:先進後出  如同一個杯子。 
隊列:先進先出 First in First out  FIFO 如同一個水管。 
 
 
*/
classDuiLie
{
privateLinkedList link;
DuiLie()
{
		link =newLinkedList();
}
publicvoid myAdd(Object obj)
{
		link.addFirst(obj);
}
publicObject myGet()
{
return link.removeLast();//return link.removeFirst();就是堆棧
}
publicboolean isNull()
{
return link.isEmpty();
}
 
 
}
classLinkedListDemo
{
publicstaticvoid main(String[] args)
{
DuiLie dl =newDuiLie();
 
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
while(!dl.isNull())
{
			sop(dl.myGet());
}
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>
 
5、Vector
Vector:底層是數組數據結構。線程同步。被ArrayList替代了。
例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
枚舉就是Vector特有的取出方式
*/
classVectorDemo
{
publicstaticvoid main(String[] args)
{
Vector v =newVector();
 
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
 
Enumeration en = v.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
}</span>
運行結果:
 
 
四、Set
 
1、Set:元素是無序的(存入和取出的順序不一定一致),元素不可以重複。     
        |--HashSet:底層數據結構是哈希表。線程不同步。保證元素唯一性的依據:判斷元素的hashCode值是否相同。如果相同,還會繼續判斷元素的equals方法,是否爲true。 
        |--TreeSet:可以對Set集合中的元素進行排序。默認按照字母的自然排序。底層數據結構是二叉樹。保證元素唯一性的依據:compareTo方法return 0。
    
2、Set集合的功能和Collection是一致的。
 
3、HashSet
HashSet:底層數據結構是哈希表。線程不同步。
保證元素唯一性的依據:判斷元素的hashCode值是否相同。如果相同,還會繼續判斷元素的equals方法,是否爲true。
注意:對於判斷元素是否存在contains,以及刪除remove等操作,依賴的方法是元素的hashcode和equals方法。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
將自定義對象作爲元素存到HashSet集合中,並去除重複元素。如存人對象,同姓名同年齡視爲同一個人
保證元素唯一性的依據:判斷元素的hashCode值是否相同。
如果相同,還會繼續判斷元素的equals方法,是否爲true。
注意:對於判斷元素是否存在contains,以及刪除remove等操作,依賴的方法是元素的hashcode和equals方法。
*/
 
classPerson
{
privateString name;
privateint age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
publicint hashCode()//重寫hashcode
{
System.out.println(this.name+"...hashcode");
return name.hashCode()+age*39;
}
publicboolean equals(Object obj)//重寫equals
{
if(!(obj instanceofPerson))
returnfalse;
Person p =(Person)obj;
System.out.println(this.name+"..."+p.name);
returnthis.name.equals(p.name)&&this.age == p.age;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classHashSetDemo
{
publicstaticvoid main(String[] args)
{
HashSet hs =newHashSet();
 
		hs.add(newPerson("a1",11));
		hs.add(newPerson("a2",12));
		hs.add(newPerson("a3",13));
		hs.add(newPerson("a2",12));
 
		sop("a1:"+hs.contains(newPerson("a1",11)));
		sop("a3:"+hs.remove(newPerson("a3",13)));
 
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p =(Person)it.next();
			sop(p.getName()+"::"+p.getAge());
}
 
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}</span>
 
4、TreeSet
TreeSet:底層數據結構是二叉樹。可以對Set集合中的元素進行排序。默認按照字母的自然排序。
保證元素唯一性的依據:compareTo方法return 0。
二叉樹:
TreeSet排序的兩種方式  
1)第一種排序方式:自然排序
        讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo方法。這種方式也被稱爲元素的自然順序,或者叫做默認順序。
2)第二種方式:比較器
        當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。
在集合初始化時,就有了比較方式。定義一個比較器,將比較器對象作爲參數傳遞給TreeSet集合的構造函數。
比較器構造方式:定義一個類,實現Comparator接口,覆蓋compare方法。
當兩種排序都存在時,以比較器爲主。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
往TreeSet集合中存儲自定義對象學生,並按照學生年齡進行排序。
排序時,當主要條件相同時,一定要判斷一下次要條件。
*/
classStudentimplementsComparable//該接口強制讓學生具備比較性
{
privateString name;
privateint age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
publicint compareTo(Object obj)//若想怎麼存怎麼取,只需返回1;倒序則返回-1即可。
{
if(!(obj instanceofStudent))
thrownewRuntimeException("不是學生對象");
Student s =(Student)obj;
 
//System.out.println(this.name+"...compareto"+s.name);
if(this.age>s.age)
return1;
if(this.age==s.age)
{
returnthis.name.compareTo(s.name);
}
return-1;
}
publicString getName()
{
return name;
}
publicint getAge()
{
return age;
}
}
classTreeSetDemo
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet();
 
		ts.add(newStudent("lisi02",22));
		ts.add(newStudent("lisi07",20));
		ts.add(newStudent("lisi09",19));
        ts.add(newStudent("lisi08",19));
        ts.add(newStudent("lisi08",19));
 
 
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu =(Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
}
}
 
publicstaticvoid sop(Object obj)
{
System.out.println(obj);
}
}
 
classMyCompareimplementsComparator//構造比較器
{
publicint compare(Object o1,Object o2)
{
Student s1 =(Student)o1;
Student s2 =(Student)o2;
 
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return  s1.getAge()- s2.getAge();
}
return num;
}
}</span>
例:按照字符串長度排序
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
//按照字符串長度排序
classTreeSetTest
{
publicstaticvoid main(String[] args)
{
TreeSet ts =newTreeSet(newStrLenComparator());
		ts.add("abd");
		ts.add("cc");
		ts.add("z");
		ts.add("hahaha");
		ts.add("zdf");
 
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
 
classStrLenComparatorimplementsComparator
{
publicint compare(Object o1,Object o2)
{
String s1 =(String)o1;
String s2 =(String)o2;
int num =newInteger(s1.length()).compareTo(newInteger(s2.length()));
if(num ==0)
return s1.compareTo(s2);
return num;
 
}
}</span>
運行結果:
 
 
五、泛型
 
1、泛型概述
泛型:JDK1.5版本以後出現的新特性。用於解決安全問題,是一個類型安全機制。
泛型格式:  通過<>來定義要操作的引用數據類型
好處:
a、將運行時期出現的問題ClassCastException,轉移到了編譯時期。方便於程序員解決問題。讓運行時期的問題減少,安全。
b、避免了強制轉化麻煩。
 
2、泛型使用
在使用java提供的對象時,什麼時候寫泛型呢?
通常在集合框架中很常見,只要見到<>就要定義泛型。
其實<>就是用來接收類型的。當使用集合時,將集合中要存儲的數據類型作爲參數傳遞到<>中即可。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
/*
泛型:JDK1.5版本以後出現的新特性。用於解決安全問題,是一個類型安全機制。
好處:
1,將運行時期出現的問題ClassCastException,轉移到了編譯時期。方便於程序員解決問題。讓運行時期的問題減少,安全。
2,避免了強制轉化麻煩。
*/
classGenericDemo
{
publicstaticvoid main(String[] args)
{
ArrayList<String> al =newArrayList<String>();//當使用集合時,將集合中要存儲的數據類型作爲參數傳遞到<>中即可。
 
		al.add("abc01");
		al.add("abc002");
		al.add("abc0003");
//al.add(4);//編譯通過,運行出現ClassCastException
 
Iterator<String> it = al.iterator();//當使用集合時,將集合中要存儲的數據類型作爲參數傳遞到<>中即可。
while(it.hasNext())
{
//String s = (String)it.next();//避免了強制轉化麻煩。
String s = it.next();
System.out.println(s+"::"+s.length());
}
}
}</span>
運行結果:
運行結果中注意:使用了未經檢查或不安全的操作的信息不見了。
 
3、泛型類、泛型方法、泛型接口
a.什麼時候定義泛型類?
當類中要操作的引用數據類型不確定的時候,
早期定義Object來完成擴展。現在定義泛型來完成擴展。
泛型類定義的泛型,在整個類中有效。在泛型類的對象明確要操作的具體類型後,所有要操作的類型就已經固定了。
b.爲了讓不同方法可以操作不同類型,而且類型還不確定。
那麼可以將泛型定義在方法上。
c.特殊之處:
靜態方法不可以訪問類上定義的泛型。
如果靜態方法操作的引用數據類型不確定,可以將泛型定義在方法上。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">classDemo<T>//泛型類
{
publicvoid show(T t)
{
System.out.println("class show:"+t);
}
public<T>void print(T t)//泛型方法
{
System.out.println("function print:"+t);
}
publicstatic<T>void method(T t)//靜態方法泛型
{
System.out.println("static method:"+t);
}
}
 
interfaceInter<T>//泛型接口
{
void show(T t);
}
 
classInterImpl<T>implementsInter<T>//泛型接口
{
publicvoid show(T t)
{
System.out.println("interface show:"+t);
}
}
 
 
classGenericDemo1
{
publicstaticvoid main(String[] args)
{
Demo<String> d =newDemo<String>();
Demo<Integer> d1 =newDemo<Integer>();
 
		d.show("haha");
		d1.show(0);
		d.print("hehe");
		d.print(newInteger(4));
		d.method("heihei");
		d.method(8);
 
 
InterImpl<String> i =newInterImpl<String>();
		i.show("hiahia");
InterImpl<Integer> i1 =newInterImpl<Integer>();
		i1.show(12);
}
}<span style="font-family: 'Microsoft YaHei'; color: rgb(190, 190, 197);"> </span></span>
運行結果:
 
4、泛型限定
?:通配符。也可以理解爲佔位符。
泛型的限定:
? extends E:可以接收E類型或E的子類型。上限。
?super E:可以接收E類型或E的父類型。下限。
代碼示例:
<span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.*;
 
classGenericDemo2
{
publicstaticvoid main(String[] args)
{
ArrayList<Person> al =newArrayList<Person>();
		al.add(newPerson("abc01"));
		al.add(newPerson("abc002"));
		al.add(newPerson("abc0003"));
 
ArrayList<Student> al1 =newArrayList<Student>();
		al1.add(newStudent("abc---01"));
		al1.add(newStudent("abc---002"));
		al1.add(newStudent("abc---0003"));
 
		printColl(al);
		printColl(al1);
 
}
publicstaticvoid printColl(ArrayList<?extendsPerson> al)
{
Iterator<?extendsPerson> it = al.iterator();
while(it.hasNext())
{
System.out.println( it.next().getName());
}
}
 
}
 
classPerson
{
privateString name;
Person(String name)
{
this.name = name;
}
publicString getName()
{
return name;
}
}
 
classStudentextendsPerson
{
Student(String name)
{
super(name);
}
}</span>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章