1. 程式人生 > >Java常用資料結構(個人筆記)

Java常用資料結構(個人筆記)

寫在前面:

樓主剛打完ACM徐州現場賽,也算是退役了,現在準備重新補一遍Java,之前一直用的是C++,所以我會結合C++來整理Java的資料結構,同時也便於理解。

那麼我將按照以下順序進行講解,感覺難度也是逐步提升

ArrayListVectorLinkedlist的用法

StackQueue的用法

Set  用法

Map 用法

下面開始我的表演

①ArrayList

ArrayList是最常用的List實現類,內部是通過陣列實現的,它允許對元素進行快速隨機訪問

其實吧,個人理解他就是個陣列,只不過封裝了,有各種操作。

定義:

    	ArrayList a = new ArrayList();
    	ArrayList<Integer> b = new ArrayList<Integer>();

這裡的Integer可以換成任何其他類。

第一種定義可以不指明ArrayList的型別,那麼插入的資料可以是任意型別;

第二種明確了型別,只能插入相應型別的資料。

操作:

1. add( Object obj );  加入元素到尾部

    	a.add(2);
    	a.add( new person("小明",1) );
    	
    	b.add(4);
    	b.add(5);

因為之前的a我們沒指名型別,所以我們可以add任意型別的東西進去,b就只能add Integer型別的。

這個絕逼是最常用的,相當於C++裡面的push_back();

至於他的返回值,是boolean,也就是C++的bool,表示是否add成功,但是返回值我們一般不用

然後add還可以指定位置

add( int index,Object obj);

      b.add(1, 222);	//在1位置處插入222,後面的元素index加1(如果有的話)

這個帶插入位置的add就相當於C++的insert,在某個位置插入一個元素,使後面的元素後移。

但是個人建議不要用這個,這個插入效率比較低。

2.get( int index );  得到指定位置的元素

    	int t = (Integer)a.get(0);  //下標是從0開始的
    	person p = (person)a.get(1);	
    	
    	int t2 = b.get(0);
    	int t3 = b.get(1);

這裡我們注意到a的get都要強制轉換,而b不需要,因為a在定義時候就沒有明確,所以這是必然的。

3.remove( int index ) 刪除指定位置的元素,後面元素向前挪

       a.remove(0);

它的返回值也是boolean,表示是否刪除成功。

同樣,因為是陣列實現,所以刪除效率就很低。

4.int size();  得到ArrayList的大小

    	int t = b.size();

常用而又簡單

5.sort( Comparator c );  進行排序,還需要定義比較器,個人覺得比較麻煩

    b.sort( new mycomparator() );
    
    //定義 mycomparator
    class mycomparator implements Comparator<Integer>
    {
	    public int compare(Integer o1, Integer o2)
	    {
	    	if( o1 > o2 )	
		    	return 1;
		    return -1;
	    }
    }

 如果覺得不太理解可以去查查Java排序的相關知識

6.void clear();  清空

		a.clear();

就和C++的clear一樣

下面是ArrayList用法小彙總,大家可以舉一反三

import java.util.*;

public class Main 
{
	
	public static void main( String args[] )
	{
		ArrayList a = new ArrayList();	//定義ArrayList  不明確型別
		
		a.add(1);
		a.add( new Person("小明",12) );
		a.add(0, 123); 					//在0位置處插入123
		int t = (int)a.get(0);			//不加強制轉化 會報錯
		System.out.println(t); 			//輸出t 結果是123
		
		a.remove(0);					//刪除位置0處的元素,後面的向前面移動	
		
		for( int i = 0 ; i < a.size() ; i++ )	//遍歷ArrayList
			System.out.println( a.get(i) );
		
		a.clear();	//清空
		if( a.isEmpty() )		//呼叫 isEmpty方法
			System.out.println("ArrayList已經空了");
		
	}
}
class Person
{
	String name;
	int age;
	Person( String name,int age )
	{
		this.name = name;
		this.age = age;
	}
	public String toString()
	{
		return "name "+name+"\n"+"age "+age;
	}
}

②Vector的用法

其實Vector和ArrayList簡直是一模一樣,至少操作是這樣

如果想了解它們的區別,可以參考

③LinkedList

LinkedList的基本用法其實和ArrayList差不多,但是它的儲存方式和之前的不一樣,所以還是有一丟丟不同。

總的來說,LinkedList   增加和刪除效率要比ArrayList要高。 畢竟是連結串列,改一下指標就行了

但是訪問的效率並不高。

定義

    	LinkedList l = new LinkedList();
    	LinkedList<Person> ll = new LinkedList<Person>();

操作:

add( Object obj)、remove(int index)、size()、isEmpty()、sort()、clear()這些都和之前的一樣,我就不講啦

不同的有:

void addFirst( Object obj );   //隊首插入

void addLast( Object obj );   //隊尾插入,和add( Object obj )效果一樣

    	l.addFirst(1);
    	l.addLast(2);

同樣remove也有兩種

Object removeFirst(  );

Object removeLast(  );

當然,返回值可以要,也可以不要

    	l.removeFirst();
    	l.removeLast();
    	
    	int t = (int)l.removeLast();
    	int t2 = (int)l.removeFirst();

下面是LinkedList的用法小彙總

import java.lang.reflect.Array;
import java.math.*;
import java.util.*;

public class Main
{
    public static void main(String[] args) 
    {
    	Person p1 = new Person("小明",12);
    	Person p2 = new Person("小紅",16);
    	Person p3 = new Person("小哥哥",13);
    	
    	LinkedList<Person> ll = new LinkedList<Person>();	//定義一個LinkedList
    	ll.add(p1);
    	ll.add(p2);
    	ll.add(p3);
    	
    	ll.sort( new mycomparator() );		//進行排序
    	ll.addFirst( new Person("大哥",22) );	
    	
    	for( int i = 0 ; i < ll.size() ; i++ )
    		System.out.println( ll.get(i) );
    	
    	ll.removeFirst();
    	ll.removeLast();
    	Person temp = ll.removeFirst();		//刪除第一個
    	ll.removeFirst();
    	
    	if( ll.isEmpty() )		//呼叫isEmpty方法
    		System.out.println("LinkedList空了");
    	else
    	{
    		Person tt = ll.get(0);	//get函式
    		ll.removeFirst();		
    	}
    	ll.clear();					//清空
    }
}
class Person
{
	String name;
	int age;
	public Person( String name,int age )
	{
		this.name = name;
		this.age = age;
	}
	public String toString()
	{
		return "name "+name+"\n"+"age "+age;
	}
}
class mycomparator implements Comparator<Person>
{
	public int compare(Person a, Person b )		//年齡從大到小排序
	{
		if( a.age < b.age )
			return 1;
		return -1;
	}
}

Stack用法

Stack意思是棧,具有先進後出的特點

與C++不同的是,Java的Stack遍歷方式可以多樣,因為Stack可以取到任意位置的值,而C++只能中規中矩的遍歷。

可見Java的操作比C++更多

定義:

    	Stack<Integer> s = new Stack<Integer>();
    	Stack ss = new Stack();

操作:

push( Object obj );  插入元素到棧頂

add( Object obj );    插入元素到尾部  效果和push一樣

    	Stack<Integer> s = new Stack<Integer>();
    	s.push(1);
    	s.add(2);

boolean empty();  判斷佇列是否為空

Object peek();    取棧頂元素

Object pop();     刪除棧頂元素,返回的是刪除的元素

int size();     返回棧的大小

結合以上幾個方法,我們可以寫出Stack的兩種遍歷方法

    	System.out.println("遍歷");
    	for( int i = s.size()-1 ; i >= 0 ; i-- )	//從後往前遍歷
    		System.out.println(s.get(i) );
    	
    	System.out.println("遍歷");
    	while( s.empty() == false )
    	{
    		int t = s.peek();	
    		s.pop();
    		System.out.println(t);
    	}

void sort();  之前已經講過啦,參加ArrayList的sort

void clear();   清空

下面是Stack用法小彙總

public class Main
{
    public static void main(String[] args) 
    {
    	Stack<Integer> s = new Stack<Integer>();
    	s.push(1);
    	s.add(2);		//add和push效果一樣
    	
    	s.push(3);
    	
    	System.out.println( "位置為 1的地方是 "+ s.elementAt(1) );	//呼叫elementAt方法
    	
    	System.out.println("從前向後遍歷");
    	for( Integer i:s )			//從前向後遍歷  用到了foreach迴圈
    		System.out.println(i);
    	
    	System.out.println("從後向前遍歷");
    	for( int i = s.size()-1 ; i >= 0 ; i-- )	//從後往前遍歷
    		System.out.println(s.get(i) );
    	
    	System.out.println("類似C++Stack的遍歷");
    	while( s.empty() == false )
    	{
    		int t = s.peek();	
    		s.pop();
    		System.out.println(t);
    	}
    	s.clear();	//清空棧
    	
    }
}

Queue用法

Queue就是佇列,具有先進先出的特點

在Java中,沒有Queue這個類,而是用到了LinkedList,所以我們定義的時候有點特殊

定義:

    	Queue q = new LinkedList();
    	Queue<String> qq = new LinkedList<String>();

操作:

boolean add( Object obj );  向佇列中插入一個元素

boolean offer( Object obj );  向佇列中插入一個元素

可以看出兩個方法的功能一樣,但是推薦使用第二個,在網上看的說add操作失敗時會丟擲異常,有點不是很明白

如果有問題的可以自己去百度一下吧

Object peek();     返回隊首元素

Object poll();   刪除並返回隊首元素

當然因為是LinkedList實現的,所以LinkedList有的操作它都有,那麼我就偷一下懶,不寫啦

下面是Queue用法小彙總

public class Main
{
    public static void main(String[] args) 
    {
    	Queue<String> q = new LinkedList<String>();		//定義一個Sting類的Queue
    	
    	q.add("1");		//向隊首加入元素
    	q.offer("1");   //功能與上一個一樣,但是推薦使用第二個
    	q.offer("2");	
    	q.offer("3");
    	
    	q.poll();		//刪除隊首元素
    	
    	String t = q.peek();	//取隊首元素
    	
    	System.out.println("foreach 遍歷佇列");
    	for( String s:q )
    		System.out.println(s);
    	
    	System.out.println("類似C++的佇列遍歷");
    	while( q.isEmpty() == false )
    	{
    		String s = q.peek();
    		q.poll();
    		System.out.println(s);
    	}
    	q.clear();
    }
}

⑥Set用法

Set表示集合,不能允許元素重複

Set又包括HashSet和TreeSet,第一個不自動排序,第二個自動排序

C++中STL有MultiSet(允許元素重複),而Java中自帶的沒有,似乎要自己去下載。

另外,Set是一個藉口,不能例項化一個Set物件

Set繼承Collection藉口,所以有Collection的常見操作

定義:

    	Set s1 = new HashSet();
    	Set s2 = new TreeSet();
    	//或者
    	HashSet s3 = new HashSet();
    	TreeSet s4 = new TreeSet();

操作:

這裡我偷一下懶,直接放張圖片,嘻嘻

下面是Set用法小彙總

public class Main
{
    public static void main(String[] args) 
    {
    	Set<String> s1 = new HashSet<String>();
    	Set<String> s2 = new TreeSet<String>();
    	
    	s1.add("ABC");
    	s1.add("ABC");
    	s1.add("AAA");
    	
    	s2.add("AB");
    	s2.add("BB");
    	s2.add("CC");
    	
    	System.out.println("遍歷HashSet");
    	Iterator<String> it = s1.iterator();	
    	while( it.hasNext() )
    	{
    		String t = it.next();
    		System.out.println(t);
    	}
    	
    	s1.remove("ABC");		//刪除ABC
    	if( s1.contains("ABC")  )		//呼叫contains方法,判斷Set是否包含某個元素
    		System.out.println("ABC 還在");
    	
    	if( s1.isEmpty() )		//使用 isEmpty方法
    		System.out.println("s1空了");
    	
    	System.out.println("遍歷TreeSet");
    	Iterator<String> it2 = s2.iterator();		//TreeSet結果會自動排序
    	while( it2.hasNext() )
    	{
    		String t = it2.next();
    		System.out.println(t);
    	}
    	s1.clear();			//清空
    	s2.clear();
    }
}

Map用法

個人感覺Map是常用的資料結構裡面最難的。

首先我們要知道map儲存資料的方式,map儲存資料的形式是一個key和一個value對應,即Map<String,String> map = new HashMap<String,String>(); 其儲存的資料型別可以是任意的。

定義:

    	Map<String,Integer> m = new HashMap<String,Integer>();	//String 到 int的對映

操作:

put( Object Key,Object Value );    插入一組值

remove( Object Key );       刪除鍵值為Key的那一組

get( Object Key );          得到鍵值為Key的那一組的Value

entrySet();             得到Pair集合(個人是這樣理解的,pair就是一組)

keySet();        得到Key集合

values();       得到values集合

要想搞清楚Map,就要先搞清楚Key,Value和Entry的區別,

例如 Map<String,Integer> m = new HashMap<String,Integer>();

中,String就是Key,Integer就是Value,而<String,Integer> 是一組Entry

所有組Entry構成了EntrySet

所有Key構成KeySet,同樣所有Value構成ValueSet

下面是Map用法小彙總:

主要理解遍歷啊

public class Main
{
    public static void main(String[] args) 
    {
    	Map<String,Integer> m = new HashMap<String,Integer>();	//String 到 int的對映
    	m.put("小明", 12);
    	m.put("小紅", 11);	//向Map中插入一組值
    	m.put("小呆", 20);
    	
    	m.remove("小呆");		//刪除Key為小呆的一組值
    	Integer t = m.get("小明");	//得到key為小明所在的值
    	System.out.println(t);		//得到結果為12
    	
    	//下面是Map的4種遍歷方法
    	
    	System.out.println("Map遍歷方法1:KeySet遍歷");  //通過Key找Value,可想效率不是很高
    	for( String key: m.keySet() )
    		System.out.println(" Key:"+key+"  "+"value:"+m.get(key) );
    	
    	System.out.println("Map遍歷方法2:ValueSet遍歷"); //只遍歷Map的value,不能遍歷Key,所以有缺陷,但是比較快
    	for( Integer i:m.values() )
    		System.out.println("value "+i);
    	
    	System.out.println("Map遍歷方法3: EntrySet遍歷");		//遍歷Map的每一組,推薦使用這種方法
    	for( Map.Entry<String, Integer> entry : m.entrySet() )
    		System.out.println(" Key "+entry.getKey()+ "  "+"value: "+entry.getValue() );
    	
    	System.out.println("Map遍歷方法4: EntrySet+Iterator遍歷");	//比較複雜
    	Iterator< Map.Entry<String,Integer> > it =  m.entrySet().iterator();
    	while( it.hasNext() )
    	{
    		Map.Entry<String, Integer> entry = it.next();
    		System.out.println(" Key "+entry.getKey()+ "  "+"value: "+entry.getValue() );//這一步和上一種遍歷一樣	
    	}
    	
    }
}

另外Map還有一個HashTable,但是兩者的差別是非常小的,而且HashTable已經快被淘汰

感興趣的可以參考下面連結

總結:

雖然我將的順序是這樣,但是分類的順序卻有些不一樣

List介面是被四個類實現了

分別是ArrayList、LinkedList、Vector、Stack

Map介面是兩個

HashMap、HashTable

Set介面是兩個

HashSet、TreeSet

Queue介面是一個

所以我想說的是,程式設計時應該養成使用介面定義的好習慣,

即如果定義ArrayList ,用  List a = new ArrayList();   而不是 ArrayList a = new ArrayList();

如果定義LinkedList   ,用 List ll = new LinkedList();   而不是 LinkedList ll = new LinkedList();

至於為什麼,

一句話,更靈活一些。

----------------------------------------------------------------------------------------------------------------------------------------------------

以上就是Java的常用資料結構啊,樓主知識短淺,還望多多指正。

第一次編輯,以後還會再回來看的。

---------------------2018/11/1