Java集合(二)

Set
  方法介紹
  特點
  List利用Set去重
  總結
Queue
  介紹
  常用操作
  總結
  PriorityQueue
    介紹
    總結
  Deque
    介紹
    Deque和Queue區別
    基本使用
    總結
Stack
  介紹
  Stack作用
總結

Set

方法介紹
  • boolean add(E e) 添加元素
  • boolean remove(Object o) 移除元素
  • boolean contains(Object o) 是否包含元素
  • int size() 元素個數
Set<String> set = new HashSet<>();
set.add("abc");	// true
set.add("xyz");	// true
set.size(); // 2
set.add("xyz");	// false
set.size();	// 2
set.contains("abc"); // true
set.remove("abc"); // true
set.size();	// 1
set.contains("abc"); // false
set.remove("test");	// false
set.size();	// 1
特點

Set用於存儲不重複的元素集合:

  • Set實際上相當於不存儲Value的Map
  • Set用於去除重複元素
  • 放入Set的元素要正確實現equals()和hashCode()

Set不保證有序:

  • HashSet是無序的
  • TreeSet是有序的
  • 實現了SortedSet接口的是有序Set
    在這裏插入圖片描述
Set<String> set = new HashSetM<>();
set.add("apple");
set.add("banana");
set.add("orange");
for (String s : set) {
  	System.out.println(s);
}
// 無序的 banana, orange, apple

Set<String> set = new TreeSet<>();
set.add("banana");
set.add("apple");
set.add("orange");
for (String s : set) {
  	System.out.println(s);
}
// 有序的 apple, banana, orange

自定義排序算法:

Set<String> set = new TreeSet<>(new Comparator<String>(){
  	public int compare(String o1, String o2) {
				// 倒序排序
      	return - o1.compareTo(o2);
    }
});
set.add("banana");
set.add("apple");
set.add("orange");
for (String s : set) {
  	System.out.println(s);
}
// 倒序的 orange, banana, apple
List利用Set去重
List<String> list = Arrays.asList("pear", "apple", "banana", "apple");
// 轉化爲set去重
Set<String> set = new HashSet<>(list);
// 或轉化爲TreeSet去重並排序
// Set<String> set = new TreeSet<>(list);
// 再轉化爲List
List<String> list1 = new ArrayList<String>(set);

// 自定義排序算法
Set<String> set2 = new TreeSet<>(new Comparator<String>() {
  	public int compare(String o1, String o2) {
      	// 倒序
      	return - o1.compareTo(o2);
    }
});
// 把list數據添加到set
set2.addAll(list);
// 再轉化爲List
List<String> list2 = new ArrayList<String>(set2);
總結
  • Set用於存儲不重複的元素集合
  • 放入Set的元素與作爲Map的Key要求相同:
    • 正確實現equals()和hashCode()
  • 利用Set可以去除重複元素
  • 遍歷SortedSet按照元素的排序順序遍歷,也可以自定義排序算法

Queue

介紹

Queue實現了一個先進先出(FIFO)的隊列

  • FIFO:First In First Out
  • LinkedList實現了Queue接口
常用操作
  • 獲取隊列長度:size()
  • 添加元素倒隊尾:boolean add(E e) / boolean offer(E e)
Queue<String> q = new LinkedList<>();
if (q.offer("abc")) {
  	// add ok
} else {
  	// add failed
}
  • 獲取隊列頭部元素並刪除:E remove() / E poll()
Queue<String> q = new LinkedList<>();
if (q.isEmpty()) {
  	// cannot poll
} else {
  	String first = q.poll();
}
  • 獲取隊列頭部元素但不刪除:E element() / E peek()
Queue<String> q = new LinkedList<>();
if (q.isEmpty()) {
  	// cannot peek
} else {
  	String first = q.peek();
}
  • 當添加或獲取元素失敗時,以上提供的兩種方法的區別:
    在這裏插入圖片描述
總結
  • Queue 實現一個先進先出(FIFO)的隊列
  • add / offer 將元素添加到隊尾
  • remove / poll 從隊首獲取元素並刪除
  • element / peek 從隊首獲取元素但不刪除
  • 避免把null添加到隊列
PriorityQueue
介紹

PriorityQueue的出隊順序與元素的優先級有關,父類AbstractQueue實現了Queue:

  • remove() / poll() / element() / peek() 總是取優先級最高的元素
  • 默認情況下PriorityQueue中的元素要實現Comparable接口,並實現compareTo方法
public class Person implements Comparable<Person> {
		private String name;
  	private int age;
  	public Person(String name, int age) {
      	this.name = name;
      	this.age = age;
    }
    @Override
    public int compareTo(Repository o) {
      	// 按name排序
        return name.compareTo(o.name);
    }  
}

public class Main {
  	public static void main(String[] arge) {
      	PriorityQueue<Person> queue = new PriorityQueue<>();
      	queue.offer(new Person("Lili", 18));
      	queue.offer(new Person("Aiice", 20))
        System.out.println(queue.peek());
      	// Person{name='Alice', age=20}
      	// compareTo方法改爲 return - name.compareTo(o.name); 降序排序
      	// 結果爲Person{name='Lili', age=18}
    }
}
  • 也可以通過自定義排序算法來排序,這樣就不用元素類實現接口了
public class Main {
  	public static void main(String[] arge) {
      	PriorityQueue<Person> queue = new PriorityQueue<>(new Comparator<Person>(){
          	@Override
            public int compare(Person1 o1, Person1 o2) {
              	// 倒序
                return - o1.name.compareTo(o2.name);
            }
        });
      	queue.offer(new Person("Lili", 18));
      	queue.offer(new Person("Aiice", 20))
        System.out.println(queue.peek());
      	// 結果爲Person{name='Lili', age=18}
    }
}
總結
  • PriorityQueue實現了一個優先隊列
  • 從隊首獲取元素時,總是獲取優先級最高的元素
  • 默認按元素比較的順序排序(必須實現Comparable接口)
  • 可以通過Comparator自定義排序算法(不用實現Comparable接口)

#####Deque

介紹

Deque實現一個雙端隊列(Double Ended Queue)繼承自Queue:

  • 既可以添加到隊尾,也可以添加到隊首
  • 既可以從隊首獲取, 又可以從隊尾獲取
Deque和Queue區別

在這裏插入圖片描述
在這裏插入圖片描述

基本使用
  • 爲了和Queue方法相區分,使用Deque時總是使用xxxFist / xxxLast方法
Deque<String> deque = new LinkedList<>();
deque.offerLast("end");
deque.offerFirst("abc");
String last = deque.peekLast();
String first = deque.peekFirst();
  • Deque的實現類:ArrayDeque, LinkedList

因爲LinkedList既實現了List接口,又實現了Deque接口,因此使用時習慣用接口類型來接收:

Deque<String> deque = new LinkedList<>();
deque.offerLast("z");

List<String> list = new LinkedList<>();
list.add("abc");

如果使用LinkedList來引用自己,則無法看出其具體是用作List還是Deque

// 不要這樣寫
LinkedList<String> obj = new LinkedList<>();
obj.offerLast("z");
總結
  • Deque 實現了一個雙端隊列(Double Ended Queue)
  • 將元素添加到隊尾 / 隊首:addLast / offerLast / addFirst / offerFirst
  • 從隊首 / 隊尾獲取元素並刪除:removeFirst / pollFirst / removeLast / pollLast
  • 從隊首 / 隊尾獲取元素但不刪除:getFirst / peekFirst / getLast / peekLast
  • 總是調用xxxFirst / xxxLast 以便與Queue的方法區分開
  • 避免把null添加到隊列

Stack

介紹

棧(Stack)是一種後進先出(LIFO)的數據結構

  • LIFO:Last In First Out
  • push(E e):把元素壓棧
  • pop(E e):把棧頂的元素“彈出”

用Deque可以實現Stack的功能:

  • push(E e):addFirst(E e)
  • pop():removeFirst()
  • peek():peekFirst()
Stack的作用
  • 方法(函數)的嵌套調用
  • 嵌套調用過多會造成棧溢出StackOverflowError
  • 將整數轉換爲十六進制表示的String:12500 -> 0x30d4
12500 / 16 = 781...44壓棧
781 / 16 = 48...d 	 把d壓棧
48 / 16 = 3...00壓棧
3 / 16 = 0...33壓棧
// 依次從棧頂取出爲 30d4
  • 將中綴表達式編譯爲後綴表達式進行計算
/*
中綴表達式:1 + 2 * (9 - 5)
編譯器編譯後
後綴表達式:1 2 9 5 - * +
計算過程:
1 2 9 5 依次壓棧
遇到-,把5和9彈出,並計算-5+9得到4,把4壓棧
遇到*,把4和2彈出,並計算4*2得到8,把8壓棧
遇到+,把8和1彈出,並計算8+1得到9,把9壓棧
計算結束,彈出9得到最終結果
*/
總結
  • 棧(Stack)是一種後進先出(LIFO)的數據結構
  • 操作棧的元素的方法
    • push(E e):壓棧
    • pop():出棧
    • peek():取棧頂元素但不出棧
  • Java使用Deque實現棧的功能,注意只調用push / pop / peek,避免調用Deque其他方法
  • 不要使用遺留類Stack
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章