黑馬程序員-Java的集合類(java中類的容器)和算法

                     -----------android培訓、java培訓、java學習型技術博客、期待與您交流!------------

                                       Java的集合類(java中類的容器)和算法
一、集合
    1、集合只用於存儲對象,集合的長度是可變的,集合可以存儲不同類型的對象;
   
    2、java的數據結構:每一個容器對數據的存儲方式不同,所以具有多種多樣的容器;
   
    3、集合中的分類和常用接口、類
 |--Collection集合接口:一組單獨的元素存儲
  |--List列表接口:元素是有序的(存入和取出的順序一致),元素都有索引(角標),元素允許重複。
   |--ArrayList:底層數據結構是數組,查詢速度快,增刪操作較慢,線程不同步
   |--LinkedList:底層數據結構是鏈表,查詢效率較低,增刪操作快,線程不同步
   |--Vector:底層是數組數據結構。線程同步。被ArrayList替代了。因爲效率低。
  |--Set集接口:元素是無序的(存入和取出的順序不一定一致),元素不允許重複,底層用到了Map
   |--HashSet:底層數據結構是哈希表,存儲的對象最好複寫hashCode和equals方法,保證元素不會重複。線程不同步。
   |--TreeSet:底層數據結構是二叉樹,可以對Set集合中的元素按自然順序進行排序,線程是不同步的。
               存儲的對象具備比較性。

 |--Map映射接口:數據是以鍵值對的形式存儲的,有的元素存在映射關係就可以使用該集合,元素不允許重複
  |--HashTable:底層數據結構是哈希表,線程同步。不允許有null鍵或值。jdk1.0效率低;
  |--HashMap:底層數據結構也是哈希表,線程不同步。允許有null鍵或值。將hashtable替代,jdk1.2效率高。 
  |--TreeMap:底層數據結構是二叉樹(紅-黑樹)。線程不同步。可通過比較器用於給Map集合中鍵進行排序。


     3、集合關係圖

 


     
     4、集合的特點
        a、集合中存儲的都是對象的引用(地址)。
        b、add方法的參數類型是Object。以便於接收任意類型對象。

二、Collection集合接口
    1、Collection定義了集合框架的共性功能。
        Collection 層次結構 中的根接口。Collection 表示一組對象,這些對象也稱爲 collection 的元素。
       一些 collection 允許有重複的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無序的。

    2、Collection的常見方法:

       a、添加:
  boolean add(Object obj);
  boolean addAll(Collection coll);
       b、刪除:
  boolean remove(Object obj);
  boolean removeAll(Collection coll);
  void clear();
       c、判斷:
  boolean contains(Object obj);
  boolean containsAll(Collection coll);
  boolean isEmpty();判斷集合中是否有元素。
       d、獲取:
  int size();
  iterator();

       e、其他:
                boolean removeAll(Collection<?> c);取差集
  boolean retainAll(Collection coll);取交集
  Object toArray();將集合轉成數組

     
三、迭代器:
    1、集合是繼承了public interface Iterable<T>接口的Iterator<T> iterator()方法。

    2、迭代器是集合的取出元素方式,會直接訪問集合中的元素,所以將迭代器通過內部類的形式來進行描述。
           該對象必須依賴於具體容器,因爲每一個容器的數據結構都不同,所以該迭代器對象是在容器中進行
       內部實現的,也就是iterator方法在每個容器中的實現方式是不同的。
      
       對於使用容器者而言,具體的實現不重要,只要通過容器獲取到該實現的迭代器的對象即可,也就是iterator方法。

    3、Iterator接口
  Iterator     iterator();
       a、Iterator接口就是對所有的Collection容器進行元素取出的公共接口。
       通過容器的iterator()方法獲取該內部類的對象。

       b、操作方法
  boolean hasNext();
  E next();
  void remove();
       注:在迭代循環中next()一次,就必須hasNext()判斷一次;連續兩次調用next()可能發生錯誤。

      

import  java.util.*;

class CollectionDemo {
	public static void  collectionBaseOperater(){
		Collection  a  =  new ArrayList();
        //增加
		a.add("java 01");
		a.add("java 02");
		a.add("java 03");
		a.add("java 04");

        //刪除
		a.remove("java 03");
		//a.clear();

        //長度
		sop("a.size():"+a.size());
        
		//是否爲空
		sop("a.contains:"+a.contains("java 03"));
        sop("a.isEmpty:"+a.isEmpty());
        
		//打印
		sop(a);

		sop("\r\n------------------------------\r\n");

        //集合操作
		Collection  a1  =  new ArrayList();
		a1.add("java 01");
		a1.add("java 02");
		a1.add("java 03");
		a1.add("java 04");

		Collection  a2  =  new ArrayList();
		a2.add("java 01");
		a2.add("java 02");
		a2.add("java 05");
		a2.add("java 06");

		//a1.retainAll(a2);//取交集
		a1.removeAll(a2);//取差集

		sop(a1);
		sop(a2);
	}

	public static void printf(Collection c){

		/*
		Iterator it = al.iterator();//獲取迭代器,用於取出集合中的元素。

		while(it.hasNext())
		{
			sop(it.next());
		}
		*/
        
		//採用for循環,使it成爲局部變量,用完就可以清除出內存,同時對象垃圾也可以回收。
		for(Iterator  it = c.iterator();it.hasNext();){
			System.out.print(it.next()+" ");
		}
		System.out.println();
	}

	public static void main(String[] args) {
		
		//collectionBaseOperater();

		String[] strArr = {"This","is ","a","java","test."};
		Collection  a  =  new ArrayList();
		for(int i=0;i<strArr.length;i++){
			a.add(strArr[i]);
		}

		printf(a);
	}

	public static void  sop(Object obj){
		System.out.println(obj);
	}
}


 

    4、ListIterator類
       a、ListIterator是Iterator的子接口。
              在迭代操作時,不可以又通過集合對象的方法操作集合中的元素,因爲會發生ConcurrentModificationException異常。
   所以,在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能對元素進行判斷,取出,刪除的操作,
   如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。該接口只能通過List集合的listIterator方法獲取。

       b、系列表迭代器,允許程序員按任一方向遍歷列表、迭代期間修改列表,並獲得迭代器在列表中的當前位置。
          只能用於List及其子類型。

       c、操作方法
  void add(E e);
  boolean hasNext();
  E next();//覆蓋了Iterator接口的方法
  void remove();
               
  //逆向遍歷,從集合的最後一個元素讀取,判斷前面有沒有元素
  boolean hasPrevious();//第一次使用的是時候爲假,如果接着previous,就會發生NoSuchElementException違例,
                        //所以要先判斷,再使用previous();
  E previous();

    
四、List列表接口及其相關類
    1、List的共性方法:特有的常見方法,有一個共性特點就是都可以操作角標。
       a、添加(插入)
  void add(int index,E element);
  boolean addAll(int index,Collection<? extends E> c);
       b、刪除
  E remove(int index);
  boolean remove(Object o);
       c、修改
  E set(int index,E element);
       d、獲取:
  E get(int index);
  int indexOf(Object o);
  int lastIndexOf(Object o);//獲取指定元素的位置。
  List<E> subList(int fromIndex,int toIndex);
  ListIterator listIterator();

    2、ArrayList類*
       (1)動態數組的數據結構,默認長度爲10,當超過時50%延長,而Vector是100%延長。
       (2)ArrayList類與List接口中方法基本一致。

       (3)ArrayList和LinkedList的大致區別:
           a、ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
           b、對於隨機訪問get和set,ArrayList覺得優於LinkedList,因爲LinkedList要移動指針。
           c、對於新增和刪除操作add和remove,LinedList比較佔優勢,因爲ArrayList要移動數據

       

import java.util.*;

class ListDemo {

	public static void sop(Object obj){
		System.out.println(obj);
	}

	public static void printf(Collection c){
		for(Iterator  it = c.iterator();it.hasNext();){
			System.out.print(it.next()+" ");
		}
		System.out.println();
	}

	public  static void listBaseOperator(List ls){
		ls.add(2,"abc6");
		sop(ls);

		//ls.remove(2);
		//sop(ls);

		ls.set(2,"abc8");
		sop(ls);

		for(int i=0;i<ls.size();i++){
			System.out.println("ls["+i+"]="+ls.get(i));
		}

		printf(ls);
        
		ls.add(3,"abc6");
		ls.add(2,"abc2");
		printf(ls);
		int index1 = ls.indexOf("abc2");
		int index2 = ls.lastIndexOf("abc2");
		System.out.println("index1="+index1+","+"index2="+index2);

		List subLs = ls.subList(1,3);
		printf(subLs);
	}


	public static void listIteratorOperator(List ls){
		/*
		
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();

			if(obj.equals("java02"))
				//al.add("java008");//在迭代過程中,準備添加或者刪除元素,發生錯誤;迭代操作時,不能同時進行集合方法的操作。
				it.remove();//將java02的引用從集合中刪除了。
			sop("obj="+obj);
		}
		sop(al);
		*/

		ListIterator li = ls.listIterator();

		sop("hasPrevious():"+li.hasPrevious());//hasPrevious():false
		//sop("pre::"+li.previous());//Exception in thread "main" java.util.NoSuchElementException
  

		while(li.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("abc2"))
				//li.add("java009");
				li.set("abc6");
		}

		while(li.hasPrevious())
		{
			sop("pre::"+li.previous());
		}
	
	    /*
		結果:
		pre::abc6
		pre::abc1
		pre::abc0
		*/

		sop("hasNext():"+li.hasNext());//hasNext():false,取到了最後,指針後面沒有元素了。
		sop("hasPrevious():"+li.hasPrevious());//hasPrevious():true

		sop(ls);
	}

	public static void main(String[] args) {
		String[] strArr = {"abc0","abc1","abc2"};
		List  ls  =  new ArrayList();
		for(int i=0;i<strArr.length;i++){
			ls.add(strArr[i]);
		}

		sop(ls);

		//listBaseOperator(ls);

        listIteratorOperator(ls);
	}
}



  

import java.util.*;

class ArrayListTest1 {

	public static void sop(Object obj){
		System.out.println(obj);
	}
	
	public static List removeRepeatElement(List li){
		List  newArr =  new ArrayList();
		//for(int i =0;i<li.size();i++){
			//Object obj = li.get(i);
			//if(!newArr.contains(obj)){
				//newArr.add(obj);
			//}
		//}

		for(Iterator it = li.iterator();it.hasNext();){
			Object obj = it.next();
			if(!newArr.contains(obj)){//調用存儲對象的equals()方法判斷。
				newArr.add(obj);
			}
		}

		return newArr;
	}

	public static void main(String[] args) {
		
		List li =  new ArrayList();
		li.add("abc0");
		li.add("abc1");
		li.add("abc2");
		li.add("abc3");
		li.add("abc1");
        
		sop(li);
		sop(removeRepeatElement(li));
	}
}


 

    3、LinkedList類*
       特有方法:
       a、增加:
  public void addFirst(E e);
  public void addLast(E e);

          在JDK1.6出現了替代方法:
  public boolean offerFirst(E e);//與addFirst方法沒有區別
  public boolean offerLast(E e);//與addLast方法沒有區別

       b、獲取
  public E getFirst();
  public E getLast();
   注:獲取元素,但不刪除元素。如果集合中沒有元素,會出現NoSuchElementException
         
   在JDK1.6出現了替代方法:
  public E peekFirst();
  public E peekLast();
   注:獲取元素,但不刪除元素。如果集合中沒有元素,會返回null。

       c、獲取刪除
  public E removeFirst();
  public E removeLast();
   注:獲取元素,但是元素被刪除。如果集合中沒有元素,會出現NoSuchElementException
       
   在JDK1.6出現了替代方法:
  public E pollFirst();
  public E pollLast();
   注:獲取元素,但是元素被刪除。如果集合中沒有元素,會返回null。 

      注:這裏不能定義成List的引用,因爲這些方法在List接口中都沒有,是LinkedList類的特有方法。

    
    

import  java.util.*;

class LinkedListDemo {
	public static void sop(Object obj){
		System.out.println(obj);
	}

	public static void printf(Collection c){
		for(Iterator  it = c.iterator();it.hasNext();){
			System.out.print(it.next()+" ");
		}
		System.out.println();
	}

	public static void main(String[] args) {
		LinkedList  link = new  LinkedList();//這裏不能定義成List的引用,因爲這些方法在List接口中都沒有,是LinkedList類的特有方法

		link.offerFirst("abc0");
		link.offerFirst("abc1");
		link.offerFirst("abc2");
		link.offerFirst("abc3");

		sop(link);

		//sop(link.peekFirst());
		//sop(link);
		//sop(link.peekFirst());
		//sop(link);

		//sop(link.pollFirst());
		//sop(link);
		//sop(link.pollFirst());
		//sop(link);

		//sop(link.peekLast());
		//sop(link);

		//sop(link.pollLast());
		//sop(link);
		printf(link);

		while(!link.isEmpty()){
			sop(link.pollLast());
		}
        
		printf(link);
	}
}



   

/*
需求:使用LinkedList模擬一個堆棧或者隊列數據結構。

分析:
     堆棧:先進後出
	 隊列:先進先出
*/

import java.util.*;

class MyStack{
	private  LinkedList link;

	MyStack(){
		link = new  LinkedList();
	}

	public void setData(Object o){
		link.offerFirst(o);
	}

	public  Object  getData(){
		return link.pollFirst();
	}

	public  boolean  isNotData(){
		return link.isEmpty();
	}
}


class MyQueue{
	private  LinkedList link;

	MyQueue(){
		link = new  LinkedList();
	}

	public void setData(Object o){
		link.offerFirst(o);
	}

	public  Object  getData(){
		return link.pollLast();
	}

	public  boolean  isNotData(){
		return link.isEmpty();
	}
}



class  LinkedListTest{

	public static void sop(Object obj){
		System.out.println(obj);
	}

	public static void main(String[] args) {
		MyQueue  mq =  new MyQueue();

		mq.setData("abc01");
		mq.setData("abc02");
		mq.setData("abc03");

		sop(mq.getData());


		MyStack  ms  =  new   MyStack();

		ms.setData("def01");
		ms.setData("def02");
		ms.setData("def03");

		sop(ms.getData());
	}
}


 

     4、List集合中用contians()判斷元素是否相同,依據是元素的equals方法。
        remove方法底層也是依賴於元素的equals方法。
       

/*
將自定義對象作爲元素存到ArrayList集合中,並去除重複元素。
比如:存人對象。同姓名同年齡,視爲同一個人。爲重複元素。

思路:
1,對人描述,將數據封裝進人對象。
2,定義容器,將人存入。
3,取出。

結論:List集合判斷元素是否相同,依據是元素的equals方法;
      remove方法底層也是依賴於元素的equals方法。
*/

import java.util.*;

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))
			return false;

		Person p = (Person)obj;
		//System.out.println(this.name+"....."+p.name);

		return ((this.name.equals(p.name))&&(this.age == p.age));
	}
	
	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;
	}
}

class ArrayListTest2 {
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}

	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newArr = new ArrayList();
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();

			if(!newArr.contains(obj))
				newArr.add(obj);
		}
		return newArr;
	}

	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add(new Person("lisi01",30));//al.add(Object obj);//Object obj = new Person("lisi01",30);
		//al.add(new Person("lisi02",32));
		al.add(new Person("lisi02",32));
		al.add(new Person("lisi04",35));
		al.add(new Person("lisi03",33));
		//al.add(new Person("lisi04",35));

		
		//al = singleElement(al);

		sop("remove 03 :"+al.remove(new Person("lisi03",33)));。

		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}

}


 

五、Set集接口及其相關類

    1、Set的共性方法
       Set接口中的方法和Collection基本一致。

    2、HashSet類*
       HashSet保證元素唯一性:通過元素的兩個方法,hashCode()和equals()方法來完成。
       如果元素的hashCode值相同,纔會判斷equals是否爲true。
       如果元素的hashcode值不同,不會調用equals。

        注意:(1)對於自定義類的存放到HashSet中元素,需要覆蓋hashCode和equals方法。
             (2)對於判斷元素是否存在,以及刪除等操作,依賴的方法是先通過hashCode()比較元素的hashcode值是否相同,
           如果相同,再繼續判斷元素的equals方法,是否爲true。
     

import  java.util.*;

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()
	{
		System.out.println(this.name+"....hashCode");
		return name.hashCode()+age*37;//37是處理name和age不同,但是相加值相同的情況
	}

	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			return false;

		Person p = (Person)obj;
		System.out.println(this.name+"...equals.."+p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}

	
	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;
	}
}


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("a2",12));
		hs.add(new Person("a3",13));
		//hs.add(new Person("a2",12));


		//sop("a1:"+hs.contains(new Person("a2",12)));
			
		hs.remove(new Person("a2",12));
		
		for(Iterator it = hs.iterator();it.hasNext();)
		{
			Person p = (Person)it.next();
			sop(p.getName()+"::"+p.getAge());
		}
	}
}


      
      

    3、TreeSet類
       a、在TreeSet集合中存儲的對象對應的類必須繼承Comparable接口,告訴它排序的方法;否則沒有辦法存儲,編譯不能通過。

       b、TreeSet判斷元素唯一性的依據:
          在集合初始化時,就有了比較方式。就是根據比較compareTo方法的返回結果是否是0,是0,就是相同元素,不存儲。

       c、TreeSet集合的底層是二叉樹進行排序的
          TreeSet排序的第一種方式:讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo方法(當主要條件相同時,需要比較次要條件)。
                            也種方式也成爲元素的自然順序,或者叫做默認順序。

     

import java.util.*;

class Student implements Comparable{//該接口強制讓學生具備比較性
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){

		//return 0; 在集合初始化時,就有了比較方式。就是根據比較compareTo方法的返回結果是否是0,是0,就是相同元素,不存儲。

		if(!(obj instanceof Student))
			throw new RuntimeException("不是學生對象");
		Student s = (Student)obj;

		//System.out.println(this.name+"....compareto....."+s.name);
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);//排序時,當主要條件相同時,一定判斷一下次要條件。
		}
		return -1;
	}

	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}

class TreeSetDemo {
	public static void main(String[] args){
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi08",19));
		//ts.add(new Student("lisi007",20));
		
		for(Iterator it = ts.iterator();it.hasNext();){
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}


 


   TreeSet的第二種排序方式:當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。
                           

                                   讓集合自身具備比較功能,定義一個類實現Comparator接口,覆蓋compare方法。
                                   定義了比較器,將比較器對象作爲參數傳遞給TreeSet集合的構造函數。

                                   當兩種排序都存在時,以比較器爲主。定義一個類,實現Comparator接口,覆蓋compare方法。
       如果自定義類實現了Comparable接口,並且TreeSet的構造函數中也傳入了比較器,那麼將以比較器
                                   的比較規則爲準。

    

import java.util.*;

class Student implements Comparable{
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Object obj){
		if(!(obj instanceof Student))
			throw new RuntimeException("不是學生對象");
		Student s = (Student)obj;

		//System.out.println(this.name+"....compareto....."+s.name);
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);
		return -1;
	}

	public String getName(){
		return name;
	}
	public int getAge(){
		return age;
	}
}

class TreeSetDemo2 {
	public static void main(String[] args){
		TreeSet ts = new TreeSet(new MyComparator());

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi08",19));
		ts.add(new Student("lisi007",23));
		
		for(Iterator it = ts.iterator();it.hasNext();){
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}



class  MyComparator implements Comparator{

	public  int compare(Object o1,Object o2){
		Student  s1 = (Student)o1;
		Student  s2 = (Student)o2;

        int num = s1.getName().compareTo(s2.getName());

		if(num ==0){//排序時,當主要條件相同時,一定判斷一下次要條件。
		}

			return  (new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())));

			//if(s1.getAge()>s2.getAge()){
				//return 1;
			//}

			//if(s1.getAge()==s2.getAge()){
				//return 0;
			//}
			//return -1;
		}

		return num;
	}
}



                               
       注:不管是在覆蓋compareTo方法時,還是覆蓋compare方法;當主要條件相同時,需要比較次要條件。

 


 

/*
需求:按照字符串長度排序。
*/


import java.util.*;


class TreeSetTest {
	public static void main(String[] args){
		TreeSet ts = new TreeSet(new MyComparator());

		ts.add("abcde");
		ts.add("cd");
		ts.add("bc");
		ts.add("dte");
		ts.add("iop");
		
		for(Iterator it = ts.iterator();it.hasNext();){
			System.out.println(it.next());
		}
	}
}



class  MyComparator implements Comparator{

	public  int compare(Object o1,Object o2){
		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;
	}
}


      

七、Map映射接口及其相關類
    1、Map<K,V>集合:
       (1) 將鍵映射到值的對象。一個映射不能包含重複的鍵;每個鍵最多隻能映射到一個值。
        該集合存儲鍵值對。一對一對往裏存。而且要保證鍵的唯一性。
 例如:地圖上,經緯度和圖片地點之間就是典型的Map關係。

       (2)Map的鍵是一個HashSet的集合。
     注:Map和Set很像,其實Set底層就是使用了Map集合。

    2、Map的共性方法
 a、添加:如果添加元素時,出現相同的鍵。那麼後添加的值會覆蓋原有鍵對應值,並put方法會返回被覆蓋的值。
  V put(K key,V value);
  void putAll(Map<? extends K,? extends V> m);

 b、刪除
  void clear();
  V remove(Object key);

 c、判斷
  boolean containsKey(Object key);
  boolean containsValue(Object value);
  boolean isEmpty();

 d、獲取
  int size();

  V get(Object key);//可以通過get方法的返回值來判斷一個鍵是否存在。通過返回null來判斷。
  
  Collection<V> values(); //獲取map集合中所有的值。

  Set<K> keySet();
  Set<Map.Entry<K,V>> entrySet();

      

import  java.util.*;


class  MapDemo{
	public static void main(String[] args) {
		Map<String,String>   map = new  HashMap<String,String>();
        
		System.out.println(map.put("100","abc00"));
		map.put("101","abc0");
		map.put("102","abc1");
		map.put("103","abc2");
		map.put("104","abc3");
		map.put("105","abc4");
		System.out.println(map.put("105","abc5"));

        System.out.println("map.containKey:"+map.containsKey("102"));
        //System.out.println("map.remove:"+map.remove("102"));

		map.put(null,"abc6");
		System.out.println("get(null):"+map.get(null));
		map.put("106",null);
		System.out.println("get:"+map.get("106"));


		Collection<String>  cl  =  map.values();
		System.out.println(cl);

		System.out.println(map);
	}
}


 

     3、map集合的兩種取出方式:
       (1)Set<k> keySet():將map中所有的鍵存入到Set集合。因爲set具備迭代器。
      所有可以迭代方式取出所有的鍵,在根據get方法。獲取每一個鍵對應的值。
      Map集合的取出原理:將map集合轉成set集合。在通過迭代器取出。

       (2)Set<Map.Entry<k,v>> entrySet()方法:
            a、將map集合中的映射關係存入到了set集合中,即Map.Entry對象。
    
     b、而這個關係的數據類型就是:Map.Entry。Entry其實就是Map中的一個static內部接口。
        定義在內部因爲只有有了Map集合,有了鍵值對,纔會有鍵值的映射關係。關係屬於Map集合中的一個內部事物。
        而且該事物在直接訪問Map集合中的元素。

     c、Map.Entry內部類有方法
   K getKey();
   V getValue();
              其實Entry也是一個接口,它是Map接口中的一個內部接口(封閉接口)
   interface Map{
    public static interface Entry{
     public abstract Object getKey();
     public abstract Object getValue();

    }
   }

   class HashMap implements Map{
    class Hahs implements Map.Entry{
     public  Object getKey(){}
     public  Object getValue(){}
    } 
   }

             注:可以看做在HashMap和TreeMap類內部實現了Entry類,把Key和Value合併成一個特殊形式的字符串,加以保存。

     

import  java.util.*;


class  MapDemo2{
	public static void readMethodByKey(Map map){
		Set<String>  set = map.keySet();
		for(Iterator<String>  it = set.iterator();it.hasNext();){
			String key  =  it.next();

			String values = (String)map.get(key);

			System.out.println("key= "+key+"->"+"values= "+values);
		}
	}

	public static void readMethodByEntry(Map map){
		Set<Map.Entry<String,String>>  entry  = map.entrySet();

		//for(Iterator  it = entry.iterator();it.hasNext();){
			//Map.Entry<String,String> mapEntry = (Map.Entry<String,String>)it.next();
		for(Iterator<Map.Entry<String,String>>  it = entry.iterator();it.hasNext();){
			Map.Entry<String,String> mapEntry = it.next();
            
			String key  = mapEntry.getKey();
			String values = mapEntry.getValue();

			System.out.println("key= "+key+"->"+"values= "+values);
		}

	}

	public static void main(String[] args) {
		Map<String,String>   map = new  HashMap<String,String>();
        
		map.put("101","abc0");
		map.put("102","abc1");
		map.put("103","abc2");
		map.put("104","abc3");
		map.put("105","abc4");

		readMethodByKey(map);
        //readMethodByEntry(map);


		System.out.println(map);
	}
}


 

    4、HashMap類*
        
     

/*
需求:每一個學生都有對應的歸屬地。
      學生Student,地址String。
      學生屬性:姓名,年齡。
      注意:姓名和年齡相同的視爲同一個學生,保證學生的唯一性。


分析:
1、描述學生。
2、定義map容器。將學生作爲鍵,地址作爲值。存入。
3、獲取map集合中的元素。
*/

import  java.util.*;

class Student implements Comparable<Student>{//使類具有自然的比較順序,爲了存入TreeSet;以及廣泛使用。
	private String name;
	private int age;

	Student(String name,int age){
		this.name = name;
		this.age = age;
	}

	public int compareTo(Student stu){//指定了類型
        
		int num = new Integer(this.age).compareTo(new Integer(stu.age));

		if(num ==0)
			return  this.name.compareTo(stu.name);

		return num;
	}
	
	public int hashCode(){
		return name.hashCode()+age*37;//37是處理name和age不同,但是相加值相同的情況
	}

	public boolean equals(Object obj){
		if(!(obj instanceof Student))
			//return false;
		    throw  new ClassCastException("Type mismatch!");

		Student p = (Student)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

	
	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;
	}

	public  String toString(){
		return  (this.name+":"+this.age);
	}
}

class  MapTest{
	public static void readMethodByKey(Map map){
		Set<Student>  set = map.keySet();
		for(Iterator<Student>  it = set.iterator();it.hasNext();){
			Student key  = it.next();

			String values =  (String)map.get(key);
			System.out.println("key= "+key+"->"+"values= "+values);
		}
	}

	public static void readMethodByEntry(Map map){
		Set<Map.Entry<Student,String>>  entry  = map.entrySet();

		for(Iterator<Map.Entry<Student,String>>  it = entry.iterator();it.hasNext();){
			Map.Entry<Student,String> mapEntry = it.next();
            
			Student key  = mapEntry.getKey();
			String values = mapEntry.getValue();

			System.out.println("key= "+key+"->"+"values= "+values);
		}

	}

	public static void main(String[] args) {
		Map<Student,String>   map = new  HashMap<Student,String>();
        
		map.put(new Student("java01",20),"abc0");
		map.put(new Student("java02",22),"abc1");
		map.put(new Student("java03",25),"abc2");
		map.put(new Student("java04",30),"abc3");
		map.put(new Student("java05",21),"abc4");

		readMethodByKey(map);
        //readMethodByEntry(map);


		System.out.println(map);
	}
}


 

    5、TreeMap類
      (1)public TreeMap(Comparator<? super K> comparator);
        

import java.util.*;

class nameComparator implements Comparator<Student>{
	public  int  compare(Student s1,Student s2){
		int  value  =  s1.getName().compareTo(s2.getName());
		if(value ==0){
			return  new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		}
		return value;
	}
}

class MapTest2 {
	public static void main(String[] args) 
	{
		Map<Student,String> map = new TreeMap(new nameComparator());

		map.put(new Student("java01",20),"abc0");
		map.put(new Student("java02",22),"abc1");
		map.put(new Student("java03",25),"abc2");
		map.put(new Student("java04",30),"abc3");
		map.put(new Student("java04",30),"abc5");
		map.put(new Student("java05",21),"abc4");

		Set<Map.Entry<Student,String>> entryset = map.entrySet();

		for(Iterator<Map.Entry<Student,String>> it = entryset.iterator();it.hasNext();){
			Map.Entry<Student,String>  me  =  it.next();

			Student stu = me.getKey();
			String  addr = me.getValue();

			System.out.println(stu+"::"+addr);
		}
	}
}



      (2)當數據之間存在這映射關係時,就要先想map集合。
      

/*
練習:
"sdfgzxcvasdfxcvdf"獲取該字符串中的字母出現的次數。

希望打印結果:a(1)c(2).....

思路1:
     1、字母->次數 :Map映射關係;
        字母爲鍵值,次數爲值

	 2、處理字符串,存入到Map中,計算次數;
        a、把字符串處理成char[];
		b、for-for循環處理;
		c、記錄每個字母次數;
		d、把字母和次數存入Map集合。

	 3、打印Map映射。

思路2:
     1、將字符串轉換成字符數組。因爲要對每一個字母進行操作。

     2、定義一個map集合,因爲打印結果的字母有順序,所以使用treemap集合。

     3、遍歷字符數組。
	    將每一個字母作爲鍵去查map集合。
	    如果返回null,將該字母和1存入到map集合中。
	    如果返回不是null,說明該字母在map集合已經存在並有對應次數。
	    那麼就獲取該次數並進行自增。,然後將該字母和自增後的次數存入到map集合中。覆蓋調用原理鍵所對應的值。

     4、將map集合中的數據變成指定的字符串形式返回。
*/


import java.util.*;

class MapTest3 {
	public static String charCount(String str){
		Map<Character,Integer> map = new TreeMap<Character,Integer>();
        /*
		char[] arr = str.toCharArray();
        for(int i =0;i<arr.length;i++){
			int count =0;
			char s = arr[i];
			for(int j=0;j<arr.length;j++){
                  if(arr[i]==arr[j])
					  count++;
			}

			map.put(new Character(arr[i]),new Integer(count));
		}
		*/

		//char[] arr = str.toCharArray();
        //for(int i =0;i<arr.length;i++){
			//Integer value = map.get(arr[i]);
			//if(value == null){
				//map.put(arr[i],1);
			//}
			//else{
				//map.put(arr[i],(value+1));
			//}
		//}

		char[] arr = str.toCharArray();
		int count =0;
        for(int i =0;i<arr.length;i++){

			if((arr[i]>='a'&&arr[i]<='z')||(arr[i]>='A'&&arr[i]<='Z')){
				count =0;
				Integer value = map.get(arr[i]);
				if(value != null)
					count = value;
				count++;
				map.put(arr[i],count);
			}
			
		}

        StringBuilder  sb = new StringBuilder();
		Set<Map.Entry<Character,Integer>> entryset = map.entrySet();
		for(Iterator<Map.Entry<Character,Integer>> it = entryset.iterator();it.hasNext();){
			Map.Entry<Character,Integer>  me  =  it.next();

			Character charc = me.getKey();
			Integer   num = me.getValue();

			sb.append(charc+"("+num+")");
		}

		return sb.toString();
	}


	public static void main(String[] args){
		String  str = "sdf-gzxcvasdfx-cvdf";

		String  s  = charCount(str);
		System.out.println(s);
	}
}


 

    6、Map擴展:把集合作爲元素存儲到Map中
       
   

/*
需求:用Map描述一個公司的結構。


銷售部:工號  姓名

開發部:工號  姓名
*/

import  java.util.*;

class Employee{

	private  String workNumber;
	private  String name;

	Employee(String workNumber,String name){
		this.workNumber = workNumber;
		this.name = name;
	}

	public String toString(){
		return   (workNumber+"::"+name);
	}

}

class MapDemo3{

	public static  void  methodOne(){
		HashMap<String,List<Employee>>  company =  new HashMap<String,List<Employee>>();
        
		List<Employee>  develop  =  new ArrayList<Employee>();
		List<Employee>  sale  =  new ArrayList<Employee>();

		company.put("sale",sale);
		company.put("develop",develop);

		sale.add(new Employee("101","abc0"));
		sale.add(new Employee("102","abc1"));

		develop.add(new Employee("103","abc2"));
		develop.add(new Employee("104","abc3"));


		Iterator<String> it = company.keySet().iterator();
		while(it.hasNext()){
			String  department = it.next();
			List<Employee> departmentName = company.get(department);
            
			System.out.println(department);
			Iterator<Employee> its = departmentName.iterator();
			while(its.hasNext()){
				Employee  employee = its.next();
				System.out.println(employee);
			}
		}
	}



    public static  void  methodTwo(){
		HashMap<String,HashMap<String,String>>  company =  new HashMap<String,HashMap<String,String>> ();
        
		HashMap<String,String>  develop  =  new HashMap<String,String>();
		HashMap<String,String>  sale  =  new HashMap<String,String>();

		company.put("sale",sale);
		company.put("develop",develop);

		sale.put("101","abc0");
		sale.put("102","abc1");

		develop.put("103","abc2");
		develop.put("104","abc3");


		Iterator<String> it = company.keySet().iterator();
		while(it.hasNext()){
			String  department = it.next();
			HashMap<String,String> departmentName = company.get(department);
            
			System.out.println(department);
			Iterator<String> its = departmentName.keySet().iterator();
			while(its.hasNext()){
				String  workNumber = its.next();
				String  name = departmentName.get(workNumber);
				System.out.println(workNumber+"::"+name);
			}
		}
	}

	public static void main(String[] args) 
	{

		methodOne();
		//methodTwo();
	}
}


 

八、比較

    1、比較器:Comparator接口
       (1)對象數組:對應自定義類的比較器需要繼承Comparator接口,和覆蓋 int compare(T o1,T o2)方法;
       (2)對象集合:對應自定義類的比較器需要繼承Comparator接口,和覆蓋 int compare(T o1,T o2)方法;
                      並通過集合的構造函數把比較器傳入。

    2、自然比較方式:Comparable接口 
       自定義類需要需要繼承Comparable接口,和覆蓋 int compareTo(T o)方法;
      

   

/*
需求:按照字符串長度排序。
*/


import java.util.*;


class TreeSetTest {
	public static void main(String[] args){
		TreeSet ts = new TreeSet(new MyComparator());

		ts.add("abcde");
		ts.add("cd");
		ts.add("bc");
		ts.add("dte");
		ts.add("iop");
		
		for(Iterator it = ts.iterator();it.hasNext();){
			System.out.println(it.next());
		}
	}
}



class  MyComparator implements Comparator{

	public  int compare(Object o1,Object o2){
		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;
	}
}


 

   
九、包裝器
    1、Collections
      (1)Collections:集合框架的工具類。裏面定義的都是靜態方法。

      (2)Collections和Collection區別:
           Collection是集合框架中的一個頂層接口,它裏面定義了單列集合的共性方法。它有兩個常用的子接口,
  List:對元素都有定義索引。有序的。可以重複元素。
  Set:不可以重複元素。無序。

           Collections是集合框架中的一個工具類。該類中的方法都是靜態的。
   提供的方法中有可以對list集合進行排序,二分查找等方法。
   通常常用的集合都是線程不安全的。因爲要提高效率。
   如果多線程操作這些集合時,可以通過該工具類中的同步方法,將線程不安全的集合,轉換成安全的。

      (3)常用算法
            a、排序
  public static <T> void sort(List<T> list,Comparator<? super T> c);
  public static <T extends Comparable<? super T>> void sort(List<T> list);//針對List接口中的對象對應的類。

           
     b、最大值
        public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);
        public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp);

            c、查找
        public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key);
        public static <T> int binarySearch(List<? extends T> list, T key,Comparator<? super T> c);

            

import java.util.*;

class StrLenComparator 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;
	}
}

class  CollectionsDemo{
	public static void main(String[] args) {
		//sortDemo();

		//maxDemo();

		binarySearchDemo();
	}

	public static void binarySearchDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");

		//Collections.sort(list);
		Collections.sort(list,new StrLenComparator());

		sop(list);

		//int index = Collections.binarySearch(list,"aaaa");
		//int index = halfSearch(list,"cc");
		int index = halfSearch2(list,"aaa",new StrLenComparator());
		sop("index="+index);
	}

    //binarySearch()方法內部的實現
	public static int halfSearch(List<String> list,String key){
		int max,min,mid;
		max = list.size()-1;
		min = 0;

		while(min<=max)
		{
			mid = (max+min)>>1;//  /2;

			String str = list.get(mid);

			int num = str.compareTo(key);
			if(num>0)
				max = mid -1;
			else if(num<0)
				min = mid + 1;
			else
				return mid;
		}
		return -min-1;//
	}

	public static int halfSearch2(List<String> list,String key,Comparator<String> cmp){
		int max,min,mid;
		max = list.size()-1;
		min = 0;

		while(min<=max)
		{
			mid = (max+min)>>1;//  /2;

			String str = list.get(mid);

			int num = cmp.compare(str,key);//自定義的比較器的比較方法
			if(num>0)
				max = mid -1;
			else if(num<0)
				min = mid + 1;
			else
				return mid;
		}
		return -min-1;
	}
	//binarySearch()方法內部的實現

	public static void maxDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		list.add("bbbbb");
		Collections.sort(list);
		sop(list);
		//String max = Collections.max(list);
		String max = Collections.max(list,new StrLenComparator());
		sop("max="+max);
	}

	public static void sortDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		
		sop(list);

		Collections.sort(list);
		//Collections.sort(list,new StrLenComparator());
		sop(list);
		
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}



     
     d、替換
        public static <T> void fill(List<? super T> list,T obj);
        public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal);
        public static void swap(List<?> list,int i,int j);

     e、反轉和反轉規則
        public static void reverse(List<?> list);

        public static <T> Comparator<T> reverseOrder();
        public static <T> Comparator<T> reverseOrder(Comparator<T> cmp);

       

import java.util.*;

//反向
class StrComparator implements Comparator<String>
{
	public int compare(String s1,String s2)
	{
		/*
		int num = s1.compareTo(s2);
		if(num>0)
			return -1;
		if( num<0)
			return 1;
		return num;
		*/

		return s2.compareTo(s1);
	}
}

class StrLenComparator 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;
	}
}

class  CollectionsDemo2{
	public static void main(String[] args) {
		//replaceDemo();
		//reverseDemo();
		//reverseorderDemo();
		shuffleDemo();
	}


	public static void shuffleDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		sop(list);

		Collections.shuffle(list);
		sop(list);
	}

	public static void reverseorderDemo(){
		//TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
		TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));

		ts.add("abcde");
		ts.add("aaa");
		ts.add("k");
		ts.add("cc");

		for(String s:ts)
		{
			System.out.println(s);
		}
	}

	public static void  reverseDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		sop(list);
        
		Collections.reverse(list);
		sop(list);
	}

	public static void replaceDemo(){
		List<String> list = new ArrayList<String>();

		list.add("abcd");
		list.add("aaa");
		list.add("zz");
		list.add("kkkkk");
		list.add("qq");
		list.add("z");
		sop(list);

		//Collections.fill(list,"pp");
		//sop(list);

        //fillPrcessList(list,2,4);
		//sop(list);
		
		Collections.swap(list,1,4);
		sop(list);
	}

	public static void fillPrcessList(List<String> list,int start,int end){
		List<String> temp  =  list.subList(start,end+1);

		Collections.fill(temp,"pp");

        for(int i=start,j=0;i<=end;i++,j++){
			Collections.replaceAll(list,list.get(i),temp.get(j));
		}	
	}

	public static void sop(Object obj){
		System.out.println(obj);
	}
}


 

     f、多線程同步
        public static <T> Collection<T> synchronizedCollection(Collection<T> c);
        public static <T> List<T> synchronizedList(List<T> list);
        public static <T> Set<T> synchronizedSet(Set<T> s);
        public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m);

              
     

    2、集合變數組:Collection接口中的toArray方法。
      (1)指定類型的數組要定義長度:
        當指定類型的數組長度小於了集合的size,那麼該方法內部會創建一個新的數組。長度爲集合的size。
        當指定類型的數組長度大於了集合的size,就不會新創建了數組。而是使用傳遞進來的數組,就會有null值存入多出來的部分。
           所以利用size()方法創建一個剛剛好的數組最優。

 (2)將集合變數組目的:
      爲了限定對元素的操作。不需要進行增刪了。

      

import java.util.*;
class  CollectionsToArray{
	public static void main(String[] args) {
		ArrayList<String> al = new ArrayList<String>();

		al.add("abc1");
		al.add("abc2");
		al.add("abc3");
		

		//String[] arr = al.toArray(new String[0]);//[abc1, abc2, abc3]

		//String[] arr = al.toArray(new String[5]);//[abc1, abc2, abc3, null, null]
		String[] arr = al.toArray(new String[al.size()]);

		System.out.println(Arrays.toString(arr));
	}
}


 

    3、Arrays類
       (1)Arrays:用於操作數組的工具類。裏面都是靜態方法。
  public static <T> void sort(T[] a, Comparator<? super T> c);
  public static void sort(Object[] a);//針對數組,任何元素組成的,包括自定義類組成的。
  public static <T> int binarySearch(T[] a,T key,Comparator<? super T> c);

       (2)將數組變成list集合:asList()
            a、把數組變成list集合好處:可以使用集合的思想和方法來操作數組中的元素。

     b、將數組變成集合,不可以使用集合的增刪方法。因爲數組的長度是固定。只能使用:
   contains();
   get();
   indexOf();
   subList();

        如果你增刪。那麼會反生UnsupportedOperationException,

     c、如果數組中的元素都是對象。那麼變成集合時,數組中的元素就直接轉成集合中的元素。
         如果數組中的元素都是基本數據類型,那麼會將該數組作爲集合中的元素存在。

 

import java.util.*;

class  ArraysDemo{
	public static void main(String[] args) {
		//int[] arr = {2,4,5};
		//System.out.println(Arrays.toString(arr));



		//String[] arr = {"abc","cc","kkkk"};
		//List<String> list = Arrays.asList(arr);
		//sop("contains:"+list.contains("cc"));
		////list.add("qq");//UnsupportedOperationException,
		//sop(list);


		int[] nums = {2,4,5};
		List li = Arrays.asList(nums);//[[I@1db9742] 等價於  List<int[]> li = Arrays.asList(nums);
		sop(li);
		
		Integer[] num = {2,4,5};
		List<Integer> lis = Arrays.asList(num);
		sop(lis);
	}

	public static boolean myContains(String[] arr,String key){
		for(int x=0;x<arr.length; x++){
			if(arr[x].equals(key))
				return true;
		}
		return false;
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}

}


 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章