《JAVA編程思想》第十一章(容器)、十六章、十七章總結

我將十一章容器部分和十七章寫在一塊,所以十六章先寫在前面。

一.十六章

1.數組和集合的區別

儲存元素的區別:數組可以存放基本數據類型,也可以存放引用數據類型,基本數據類型存放的是數值,而引用數據類型存放的是地址值。集合只能存放引用數據類型(對象),基本數據類型會被JAVA的自動裝箱機制,變成對象。

儲存長度:數組在創建時,就必須規定好長度,後不能改變。而集合可以隨時改變它的長度。

對元素的訪問:數組使用的是[],而集合則是添加add,獲取get等方法。

數組唯一的優勢就是效率高一點,但在平時開發過程中,優先使用集合。

2.Arrays一些常用功能

1.arraycopy()方法

這個方法裏有四個參數,第1個參數,被複制數組;第2個參數,被複制數組複製的起始位置;第3個參數,複製到的數組;第4個參數,複製到的數組複製的起始位置;第5個參數,複製多少個。

arrayCopy( arr1, 2, arr2, 5, 10);意思是;將arr1數組裏從索引爲2的元素開始, 複製到數組arr2裏的索引爲5的位置, 複製的元素個數爲10個.。

tips:複製一維數組沒有問題,複製二維數組時,改變一個另一個也會跟着改變。因爲二維數組就是元素是一維數組的一維數組,相當於元素時引用類型了。有指向性了

 

2.equals()方法

Arrays.equals(a1,a2)  比較a1,a2兩個數組,相同返回true

 

3.comparable接口和comparator接口

先說說comparable接口,是排序接口。首先需要我們要排序的類來實現此接口。然後重寫一下compareTo()方法,下面的例子明顯規定了比較的是年齡。若一個類實現了Comparable接口,就意味着該類支持排序。實現了Comparable接口的類的對象的列表或數組可以通過Collections.sort或Arrays.sort進行自動排序。

下面是格式:

目前對象.compareTo(需要比較的對象)

實現比較大小,

  • 如果返回值等於零:o1=o2
  • 返回值大於零則o1>o2
  • 返回值小於於零則o1<o2
class Person implements Comparable<Person> {

	String name;
	int age;
	public Person(String name,int age) {
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	@Override
	public int compareTo(Person o) {
		return this.age-o.age;
	}
}
public class ComparableTest {

	public static void main(String[] args) {
		List<Person> personList = new ArrayList<P>();
		personList.add(new Person("ace",22));
		personList.add(new Person("xb",21));
		personList.add(new Person("glm",36));
		personList.add(new Person("sxy",20));

		System.out.println("比較大小");
		Person ace = new Person("ace",22);
		Person xb = new Person("xb",21);
		String result = ace.compareTo(xb)==0?"一樣大":ace.compareTo(xb)>0?"ace大":"xb大";
		System.out.println(result);
		
		System.out.println("按照年齡");
		Collections.sort(personList);//Arrays.sort也行
		for(Person p:personList)
			System.out.println(p);
		System.out.println();
	}

}

上面的列子,完整展示了comparable接口的使用。下面再來說comparator接口的使用,先建立一個“該類的比較器”來進行排序,這個“比較器”只需要實現Comparator接口即可。也就是說,我們可以通過實現Comparator來新建一個比較器,然後通過這個比較器對類進行排序。

note:

1、若一個類要實現Comparator接口:它一定要實現compare(T o1, T o2) 函數,但可以不實現 equals(Object obj) 函數。

2、int compare(T o1, T o2) 是“比較o1和o2的大小”。返回“負數”,意味着“o1比o2小”;返回“零”,意味着“o1等於o2”;返回“正數”,意味着“o1大於o2”。

同樣拿person類來舉例

class Person{
	String name;
	int age;
	public Person(String name,int age) {
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

//單獨自定義一個類,而不是寫在Person類裏面
class PersonSortByAge implements Comparator<Person>{
	@Override
	public int compare(Person o1, Person o2) {
		return o1.age-o2.age;
	}
}
//在主方法裏使用
public class ComparatorTest {

	public static void main(String[] args) {

		List<Person> personList = new ArrayList<Person>();
		personList.add(new Person("ace",22));
		personList.add(new Person("xb",21));
		personList.add(new Person("glm",36));
		personList.add(new Person("sxy",20));
        //在sort()方法裏使用匿名類創建匿名對象,來排序
		personList.sort(new PersonSortByAge());
		for(Person p:personList)
			System.out.println(p);
		
	}
}

這樣就完成按照Person的年齡進行排序。總結一下兩者的區別

1.Comparable是排序接口,若一個類實現了Comparable接口,就意味着“該類支持排序”。而Comparator是比較器,我們若需要控制某個類的次序,可以建立一個“該類的比較器”來進行排序。

2.Comparable相當於“內部比較器”,而Comparator相當於“外部比較器”。前者屬於靜態綁定,後者屬於動態綁定。

兩種方法各有優劣, 用Comparable 簡單, 只要實現Comparable 接口的對象直接就成爲一個可以比較的對象,但是需要修改源代碼。 用Comparator 的好處是不需要修改源代碼, 而是另外實現一個比較器, 當某個自定義的對象需要作比較的時候,把比較器和對象一起傳遞過去就可以比大小了, 並且在Comparator 裏面用戶可以自己實現複雜的可以通用的邏輯,使其可以匹配一些比較簡單的對象,那樣就可以節省很多重複勞動了。

 

4.Arrays.binarySearch()方法

https://blog.csdn.net/wanderlustLee/article/details/79208630

首先,binarySearch方法爲二分法查找,所以數組必須是有序的或者是用sort()方法排序之後的。

格式: binarySearch(Object[], Object key) 方法的object[]參數是要查找的數組,key參數爲要查找的key值。

方法的返回值有幾種:

1.找到的情況下:如果key在數組中,則返回搜索值的索引。

2.找不到的情況下:

 [1] 搜索值不是數組元素,且在數組範圍內,從1開始計數,得“ - 插入點索引值”;
 [2] 搜索值不是數組元素,且大於數組內元素,索引值爲 – (length + 1);
 [3] 搜索值不是數組元素,且小於數組內元素,索引值爲 – 1。

舉例:

int a[] = new int[] {1, 3, 4, 6, 8, 9};  
        int x1 = Arrays.binarySearch(a, 5);  
        int x2 = Arrays.binarySearch(a, 4);  
        int x3 = Arrays.binarySearch(a, 0);  
        int x4 = Arrays.binarySearch(a, 10);
//結果爲:x1=-4      x2=2    x3=-1    x4=-7

第二種參數形式:

binarySearch(Object[], int fromIndex, int toIndex, Object key)  方法的object[]參數爲要查找的數組,fromindex參數爲開始索引(包括),toindex爲結束索引(不包括),兩個參數之間爲查找的範圍。key爲要查找的key。

方法的返回值有幾種:

1.找到的情況下:如果key在數組中,則返回搜索值的索引。

2.找不到的情況下:

 [1] 該搜索鍵在範圍內,但不是數組元素,由1開始計數,得“ - 插入點索引值”;
 [2] 該搜索鍵不在範圍內,且小於範圍(數組)內元素,返回–(fromIndex + 1);
 [3] 該搜索鍵不在範圍內,且大於範圍(數組)內元素,返回 –(toIndex + 1)。

舉例:

 int a[] = new int[] {1, 3, 4, 6, 8, 9};  
        int x1 = Arrays.binarySearch(a, 1, 4, 5);  
        int x2 = Arrays.binarySearch(a, 1, 4, 4);  
        int x3 = Arrays.binarySearch(a, 1, 4, 2);  
        int x4 = Arrays.binarySearch(a, 1, 4, 10);
//結果爲   x1=-4    x2=2    x3=-2    x4=-5

 

十一章和十七章(初步總結,不斷修訂)

一.collection總結

這個圖片裏包含了整個collection中完整全部內容,非常全面。

首先必須明確的是collection:定義的是所有單列集合中共性的方法,所有的單列集合都可以使用共性方法。

Collection 接口有 3 種子類型集合: List、Set 和 Queue(圖中),再下面是一些抽象類,最後是具體實現類,常用的有 ArrayList、LinkedList、HashSet、LinkedHashSet、TreeSet 等等。

Ⅰ Collection 集合常用方法

Ⅱ 上圖中的Iterator接口(迭代器)

1.迭代器的概念:Collection集合元素的通用獲取方式。在取元素之前先判斷集合中有沒有元素,如果有,就把這個元素取出來;繼續判斷,如果還有就再取出來。

2.爲什麼需要迭代器?因爲Collection集合中有許多的容器,比如一開始你使用的是List,但後來由於各種原因改用了Set,原來針對List編寫的遍歷程序全部要重寫了。所以我們在遍歷容器時,不關心它具體是什麼容器,我們只想要一個通用的遍歷方法。

3.迭代器使用步驟:

   1.使用集合中的方法 iterator()獲取迭代器的實現對象,使用Iterator接口來接受(多態)。

   2.使用Iterator接口中的方法hasNext判斷還有沒有下一個元素。

   3.使用Iterator接口中的方法next取出集合中的下一個元素。

實現代碼:

 

Ⅲ Listlterator接口

特點:

1.只能用於List容器

2.Iterator接口只能向前,而這個可以向前向後。

3.ListIterator還可以返回指向對象前一個和後一個的索引,並可以用set()方法,替換你最後一個訪問的元素。

4.不像Iterator接口只能從容器一開始向後移動,ListIterator可以通過listIterator(n)方法,指定索引位置開始向後。

代碼實現:

 

Ⅳ 增強for循環

首先明確增強for循環底層也是迭代器,目的是爲了簡化迭代器的書寫。

tips:增強for循環只能用來遍歷數組和集合。

格式: for(集合/數組的數據類型  變量名 : 集合名/數組名){}

代碼實現如下:

 

二.List集合總結

Ⅰ List集合特點

1.有序的集合,儲存元素和取出元素的順序是一致的。

2.有索引,所以包含了一些帶索引的方法

3.允許存儲重複的元素

 

Ⅱ List獨有的帶索引的方法

1.public void add(int index, E element):在指定索引位置,添加元素

2.public E get(int index):返回集合中指定位置的元素

3.public E remove(int index):移除這個索引的元素

4.public E set(int index,E elemet):用指定元素(第二個參數),去替換索引位置的元素。

 

List集合主要包含了兩個容器,一個就是非常熟悉的ArrayList,另一個就是LinkedList。ArrayList底層是數組,所以查找快,插入刪除慢些。LinkedList底層是鏈表,正好與之相反。需要大量的隨機訪問的時候,肯定首選ArrayList,需要大量增刪的時候,首選Linkedlist。

Ⅲ LinkedList特有的方法

1.public void addFirst(E e):將指定元素插入表頭

2.public void addLast(E e):將指定元素插入表尾

3.public void push(E e):將指定元素推入堆棧(因爲LinkedList是可以去實現Stack 和queue)

4.public void pop():從堆棧中彈出元素

5.public E getFirst():返回表頭元素

6.public E getLast():返回表尾元素

7.public E removeFirst():移除並返回表頭元素

8.public E removeLast():移除並返回表尾元素

9.public boolean isEmpty():如果列表不包含元素,則返回true

 

三.Set集合總結

Ⅰ Set集合特點

Set集合特點就是沒有重複的元素,且沒有索引。在每次存入元素前,都會檢查Set中是否已經有這個元素了,這裏就要用到equals()和hashcode()這兩個方法。

Set集合裏包含三個,HashSet 、TreeSet、LinkedHashSet 。HashSet就是查找速度快,底層就是散列表實現,儲存順序並不是安裝存入順序。TreeSet底層是紅黑樹實現,裏面儲存的元素都會被排序,元素必須要實現Comparable接口,所以將TreeSet中的元素輸出時,相當於都是排序過的。

LinkedHashSet 特點就是裏面儲存順序和存入順序是一致的,底層是散列表和鏈表實現。

 

Ⅱ 如何選擇使用

Ⅲ SortedSet

SortedSet類其實就是TreeSet的基本實現,裏面所有元素也是經過排序的。

格式:

SortedSet<String> set = new TreeSet<String>();

一些常用方法:

//返回此 set 中當前第一個(最低)元素
String fe = set.first();
//返回此 set 中當前最後一個(最高)元素。
String le = set.last();
//返回此 set 的部分視圖,其元素嚴格小於 toElement。
SortedSet<String> headE = set.headSet("ccc");
//返回此 set 的部分視圖,其元素大於等於 fromElement。
SortedSet<String> tailE = set.tailSet("ccc");
//返回此 set 的部分視圖,其元素從 fromElement(包括)到 toElement(不包括)。
SortedSet<String> subE = set.subSet("ccc", "eee");

四.隊列

除了併發以外,實現隊列有兩個,一個是LinkedList,另一個是PriorityQueue(優先隊列)。

Ⅰ  Queue的一些常用方法

add(E)其實是collection的通用方法, offer(E) 都爲添加方法,不同之處在於 add() 方法在添加失敗(比如隊列已滿)時會報 一些運行時錯誤 ;而 offer() 方法即使在添加失敗時也不會奔潰,只會返回 false。

remove(), poll() 刪除並返回頭部元素,當隊列爲空時 remove() 方法會報 NoSuchElementException 錯; 而 poll() 不會奔潰,只會返回 null。

element(), peek() 獲取但不刪除,當隊列爲空時 element() 拋出異常;peek() 不會奔潰,只會返回 null。

Ⅱ PriorityQueue(優先隊列)

優先隊列,輸出順序就不和普通的隊列是一樣的了,它遵循的是一個優先情況,就是優先級別。支持你自定義Comparable,如果沒有自定義那就是按照自然順序。由小到大。

如下面優先隊列儲存着Integer類型的元素:

public class CreatePriorityQueueExample {
    public static void main(String[] args) {
        // Create a Priority Queue
        PriorityQueue<Integer> numbers = new PriorityQueue<>();

        // Add items to a Priority Queue (ENQUEUE)
        numbers.add(750);
        numbers.add(500);
        numbers.add(900);
        numbers.add(100);

        // Remove items from the Priority Queue (DEQUEUE)
        while (!numbers.isEmpty()) {
            System.out.println(numbers.remove());
        }

    }
}

# Output
100
500
750
900

優先隊列儲存着String類型的元素:

public class CreatePriorityQueueStringExample {
    public static void main(String[] args) {
        // Create a Priority Queue
        PriorityQueue<String> namePriorityQueue = new PriorityQueue<>();

        // Add items to a Priority Queue (ENQUEUE)
        namePriorityQueue.add("Lisa");
        namePriorityQueue.add("Robert");
        namePriorityQueue.add("John");
        namePriorityQueue.add("Chris");
        namePriorityQueue.add("Angelina");
        namePriorityQueue.add("Joe");

        // Remove items from the Priority Queue (DEQUEUE)
        while (!namePriorityQueue.isEmpty()) {
            System.out.println(namePriorityQueue.remove());
        }

    }
}

# Output
Angelina
Chris
Joe
John
Lisa
Robert

也可以自己定義如何比較,比較什麼,這裏採用的new一個Comparator對象。

public class PriorityQueueCustomComparatorExample {
    public static void main(String[] args) {
        // A custom comparator that compares two Strings by their length.
        Comparator<String> stringLengthComparator = new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        };

        // Create a Priority Queue with a custom Comparator
        PriorityQueue<String> namePriorityQueue = new PriorityQueue<>(stringLengthComparator);

        // Add items to a Priority Queue (ENQUEUE)
        namePriorityQueue.add("Lisa");
        namePriorityQueue.add("Robert");
        namePriorityQueue.add("John");
        namePriorityQueue.add("Chris");
        namePriorityQueue.add("Angelina");
        namePriorityQueue.add("Joe");
        while (!namePriorityQueue.isEmpty()) {
            System.out.println(namePriorityQueue.remove());
        }
    }
}

# Output
Joe
John
Lisa
Chris
Robert
Angelina

優先隊列的底層原理:使用二叉小頂堆來實現,具體地看下數據結構那塊的總結。

五.Map

Map裏面的元素都是一個個鍵值對,鍵(key)和值(value)完全是一一對應的,鍵不能重複而值可以重複。

Ⅰ  Map的一些常用方法

1.public V put(K key , V value): 把指定的鍵與指定的值添加到Map集合。存儲鍵值對的時候,key重複,會使用新的value 替換Map中重複的value,返回被替代的value值。

2.public V remove(Object key):刪除對應鍵的元素,key存在的話,返回被刪除的值。key不存在的話,返回null。

3.public V get(Object key):獲取鍵值。若key存在的話,返回對應的value值。若key不存在,返回null。

4.boolean containsKey(Object key):判斷集合中是否已經有這個鍵了

5.boolean containsValue(V value ):判斷集合中是否已經有這個值了

Ⅱ Map集合遍歷

有四種方法區遍歷Map集合,一般用前兩種。

/**
* 最常見也是大多數情況下用的最多的,一般在鍵值對都需要使用
 */
Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黃色");

//方法一:在for循環中使用entries實現Map的遍歷:
for(Map.Entry<String, String> entry : map.entrySet()){
    String mapKey = entry.getKey();
    String mapValue = entry.getValue();
    System.out.println(mapKey+":"+mapValue);
}
//方法二:在for循環中遍歷key或者values,一般適用於只需要map中的key或者value時使用,在性能上比使用entrySet較好;
for(String key : map.keySet()){
    System.out.println(key);
}
for(String value : map.values()){
    System.out.println(value);
}
//方法三:通過Iterator遍歷;
Iterator<Entry<String, String>> entries = map.entrySet().iterator();//創建迭代器對象
while(entries.hasNext()){
    Entry<String, String> entry = entries.next();
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println(key+":"+value);
}
//方法四:通過鍵找值遍歷,這種方式的效率比較低,因爲本身從鍵取值是耗時的操作;
for(String key : map.keySet()){
    String value = map.get(key);
    System.out.println(key+":"+value);
}

Ⅲ 各種Map的特點:

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