1.集合概述
集合框架:
集合框架是一個用來代表和操縱集合的統一架構。所有的集合框架都包含如下內容:
- **接口:**是代表集合的抽象數據類型。例如 Collection、List、Set、Map 等。之所以定義多個接口,是爲了以不同的方式操作集合對象
- **實現(類):**是集合接口的具體實現。從本質上講,它們是可重複使用的數據結構,例如:ArrayList、LinkedList、HashSet、HashMap。
- **算法:**是實現集合接口的對象裏的方法執行的一些有用的計算,例如:搜索和排序。這些算法被稱爲多態,那是因爲相同的方法可以在相似的接口上有着不同的實現。
除了集合,該框架也定義了幾個 Map 接口和類。Map 裏存儲的是鍵/值對。儘管 Map 不是集合,但是它們完全整合在集合中。
collection 接口
是Collection層次結構中的根接口。Collection表示一組對象,稱爲collection的元素,一些collection允許有重複的元素,而一些則不允許,可以有序,或無序。此接口不提供任何直接實現,只提供更具體的子接口(如set和list實現)。此接口用來傳遞collection,並且在最大普遍性的地方操作這些collection。
2.List
public interface List< E > extends Collection< E >
有序的collection,也稱爲序列。此接口的用戶可以對列表中每個元素的插入位置進行精確的控制。用戶可以根據元素的整數索引(在列表中的位置)訪問元素,並搜索列表中的元素。
常用的有:ArrayList Vector LinkedList
public class ListDemo {
private static void arrayList(){
List<String> list = new ArrayList<>();
list.add("xxx");
list.add("yyy");
list.add("zzz");
// list.add(10);//未聲明list保存的類型時,可以保存多種類型的元素
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
if(list.contains("xxx")){
System.out.println("contain xxx");
}
list.remove("yyy");
String[] array = list.toArray(new String[]{});
for(String s:array){
System.out.println(s);
}
}
public static void main(String[] args) {
arrayList();
}
}
2.1 ArrayList
實現原理:
- 採用動態數組實現,默認構造方法創建了一個空數組
- 第一次添加元素,擴展容量爲10,之後的擴充算法:原來數組大小+原來數組大小的一半
- 不適合進行刪除或插入操作
- 爲了防止數組動態擴充次數過多,建議創建ArrayList時,給定初始容量
- 線程不安全,適合單線程訪問時使用,效率高。
2.2 Vector
實現原理:
- 採用動態數組實現,默認構造方法創建了一個大小爲10的對象數組
- vector的擴充算法:當增量爲0時,擴充爲原來大小的兩倍,當增量大於0時,擴充爲原來大小+增量。增量可以在初始化時給定
- 不適合進行刪除或插入操作
- 爲了防止數組動態擴充次數過多,建議創建Vector時,給定初始容量
- 線程安全,適合在多線程訪問時使用,在單線程下使用效率低
2.3 LinkedList
實現原理:
- 採用雙向鏈表結構實現
- 適合插入,刪除操作,性能高
2.4 Vector和ArrayList和LinkedList的區別
- ArrayList是最常用的List實現類,內部是通過數組實現的,它允許對元素進行快速隨機訪問。數組的缺點是每個元素之間不能有間隔,當數組大小不滿足時需要增加存儲能力,就要講已經有數組的數據複製到新的存儲空間中。當從ArrayList的中間位置插入或者刪除元素時,需要對數組進行復制、移動、代價比較高。因此,它適合隨機查找和遍歷,不適合插入和刪除。
- Vector與ArrayList一樣,也是通過數組實現的,不同的是它支持線程的同步,即某一時刻只有一個線程能夠寫Vector,避免多線程同時寫而引起的不一致性,但實現同步需要很高的花費,因此,訪問它比訪問ArrayList慢。
- LinkedList是用鏈表結構存儲數據的,很適合數據的動態插入和刪除,隨機訪問和遍歷速度比較慢。另外,他還提供了List接口中沒有定義的方法,專門用於操作表頭和表尾元素,可以當作堆棧、隊列和雙向隊列使用。
- vector是線程(Thread)同步(Synchronized)的,所以它也是線程安全的,而Arraylist是線程異步(ASynchronized)的,是不安全的。如果不考慮到線程的安全因素,一般用Arraylist效率比較高。
- 如果集合中的元素的數目大於目前集合數組的長度時,vector增長率爲目前數組長度的100%,而arraylist增長率爲目前數組長度的50%.如過在集合中使用數據量比較大的數據,用vector有一定的優勢。
- 如果查找一個指定位置的數據,vector和arraylist使用的時間是相同的,都是0(1),這個時候使用vector和arraylist都可以。而如果移動一個指定位置的數據花費的時間爲0(n-i)n爲總長度,這個時候就應該考慮到使用Linkedlist,因爲它移動一個指定位置的數據所花費的時間爲0(1),而查詢一個指定位置的數據時花費的時間爲0(i)。
- ArrayList 和Vector是採用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,都允許直接序號索引元素,但是插入數據要設計到數組元素移動 等內存操作,所以索引數據快插入數據慢,Vector由於使用了synchronized方法(線程安全)所以性能上比ArrayList要差,LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行向前或向後遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入數度較快!
實際開發中如何選擇list的具體實現:
- 是否考慮安全性問題
- 是否頻繁插入,刪除操作
- 是否是存儲後遍歷
3.Set
public interface Set< E > extends Collection< E >
一個不包含重複元素的collection,且最多包含一個null對象,無序。常用實現類:HashSet, TreeSet, LinkedHashSet
3.1 HashSet
實現原理:
- 基於哈希表(HashMap)實現
- 不允許重複,可以有一個null元素
- 不保證順序恆久不變
- 添加元素時把元素作爲HashMap的key來存儲,HashMap的value使用一個固定的object對象
- 排除重複元素是通過equals來檢查對象是否相同
- 判斷兩個對象是否相同,先判斷兩個對象的hashCode是否相同(如果兩個對象的hashCode相同,不一定是同一個對象,如果不同,那一定不是同一個對象),如果不同,則兩個對象不是同一個對象。如果相同,還要進行equals判斷,equals相同則是同一個對象,不同則不是同一個對象。
- 自定義對象要認爲屬性值都相同時爲同一個對象,有這種需求時,我們要重寫對象所在的hashCode和equals方法。
public class SetDemo {
private static void hashSet(){
Set<String> set = new HashSet<>();
set.add("xxx");
set.add("yyy");
set.add("xxx");//重複插入,只會保存一個
System.out.println(set.size());
String[] names = set.toArray(new String[]{});
for(String s:names){
System.out.println(s);
}
//插入的是對象
Cat c1 = new Cat("xxx",4,1);
Cat c2 = new Cat("yyy",5,3);
Cat c3 = new Cat("zzz",1,4);
Cat c4 = new Cat("xxx",4,1);
Set<Cat> cats = new HashSet<>();
cats.add(c1);
cats.add(c2);
cats.add(c3);
cats.add(c4);
System.out.println(cats.size());//當cat類沒有複寫hashCode和equals方法時,這裏的大小是4,因爲是不同的對象,如果有複寫,則是3
for(Cat c:cats){
System.out.println(c);
}
System.out.println("c1="+c1.hashCode()%16);
System.out.println("c2="+c1.hashCode()%16);
System.out.println("c3="+c1.hashCode()%16);
System.out.println("c4="+c1.hashCode()%16);
}
public static void main(String[] args) {
hashSet();
}
}
public class Cat {
private String name;
private int age;
private int id;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cat cat = (Cat) o;
return age == cat.age &&
id == cat.id &&
Objects.equals(name, cat.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age, id);
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
public Cat(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
3.2 TreeSet
基於TreeMap的NavigableSet實現。使用元素的自然順序對元素進行排序,或者根據創建set時提供的Comparator進行排序,具體取決於使用的構造方法。
TreeSet 是有序的,基於TreeMap(二叉樹數據結構),對象需要比較大小,通過對象比較器來實現,對象比較器還可以取出重複元素。如果自定義的數據類沒有實現比較器Comparator這個接口,將無法添加到TreeSet中。
public class CatComparator implements Comparator<Cat> {
@Override
public int compare(Cat cat, Cat t1) {
return cat.getAge()-t1.getAge();
}
}
public class SetDemo {
private static void treeSet(){
TreeSet<Cat> tree = new TreeSet<>(new CatComparator());//需要實現比較器
Cat c1 = new Cat("xxx",4,1);
Cat c2 = new Cat("yyy",5,3);
Cat c3 = new Cat("zzz",1,4);
Cat c4 = new Cat("xxx",4,1);//相同的沒有插進去
tree.add(c1);
tree.add(c2);
tree.add(c3);
tree.add(c4);
System.out.println(tree.size());
for(Cat c:tree){
System.out.println(c);
}
}
public static void main(String[] args) {
treeSet();
}
}
/*
3
Cat{name='zzz', age=1, id=4}
Cat{name='xxx', age=4, id=1}
Cat{name='yyy', age=5, id=3}
*/
3.3 LinkedHashSet
具有可預知迭代順序的Set接口的哈希表和鏈接列表實現。此實現與HashSet的不同之處在於,其維護着一個運行於所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,即將元素插入到set中的順序(插入順序)進行迭代。插入順序不受set中重新插入的元素的影響。(如果在s.contains(e)返回true後立即調用s.add(e),則元素e會被重新插入到set s中。如果實現了hashCode和equals方法,則不會重複插入)。
這樣做的意義或者好處就是LinkedHashSet中的元素順序是可以保證的,也就是說遍歷序和插入序是一致的。
public class SetDemo {
private static void linkedHashSet(){
LinkedHashSet<Cat> tree = new LinkedHashSet<>();
Cat c1 = new Cat("xxx",4,1);
Cat c2 = new Cat("yyy",5,3);
Cat c3 = new Cat("zzz",1,4);
Cat c4 = new Cat("xxx",4,1);//相同的沒有插進去
tree.add(c1);
tree.add(c2);
tree.add(c3);
tree.add(c4);
System.out.println(tree.size());
for(Cat c:tree){
System.out.println(c);
}
}
public static void main(String[] args) {
linkedHashSet();
}
}
/*
3
Cat{name='xxx', age=4, id=1}
Cat{name='yyy', age=5, id=3}
Cat{name='zzz', age=1, id=4}
*/
4.集合的遍歷
-
foreach
-
Iterator
對collection進行迭代的迭代器
方法 介紹 boolean hasNext() 如果仍有元素可以迭代,則返回true E next() 返回迭代的下一個元素 void remove() 從迭代器指向的collection中移除迭代器返回的最後一個元素 -
ListIterator 列表迭代器,允許程序按任一方向遍歷列表,迭代期間修改列表,並獲得迭代器在列表中的當前位置。
介紹 void add(E e) 增加元素 boolean hasPrevious() 判斷是否有前一個元素 E previous() 取出前一個元素 void set(E e) 修改元素的內容 int previousIndex() 前一個索引位置 int nextIndex() 下一個索引位置 -
Enumeration 實現Enumeration接口的對象,它生成一系列元素,一次生成一個。連續調用nextElement方法將返回一系列的連續元素。
注:此接口的功能與Iterator接口的功能重複,建議使用Iterator
方法 介紹 boolean hasMoreElements() 判斷是否有下一個元素 E nextElement() 取出當前元素 public class IteratorDemo { //foreach private static void foreach(Collection<Cat> c){ for(Cat cat:c){ System.out.println(cat); } System.out.println("--------------------"); c.forEach((Cat cat) -> { System.out.println(cat); }); System.out.println("--------------------"); c.forEach( cat -> { System.out.println(cat); }); System.out.println("--------------------"); c.forEach(System.out::println); } //iterator private static void iterator(Collection<Cat> c){ Iterator<Cat> iter = c.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); } } private static void enumeration(){ Vector<String> vs = new Vector<>(); vs.add("xxx"); vs.add("yyy"); Enumeration<String> es = vs.elements(); while (es.hasMoreElements()){ System.out.println(es.nextElement()); } } public static void main(String[] args) { List<Cat> list = new ArrayList<>(); Cat c1 = new Cat("xxx",4,1); Cat c2 = new Cat("yyy",5,3); Cat c3 = new Cat("zzz",1,4); Cat c4 = new Cat("x7x",4,1); list.add(c1); list.add(c2); list.add(c3); list.add(c4); foreach(list); // iterator(list); // enumeration(); } }
5.Map
public interface Map<k ,V>
將鍵映射到值的對象,一個映射不能包含重複的鍵,每個鍵最多隻能映射到一個值。
具體的實現類:HashMap, TreeMap, Hashtable, LinkedHashMap
方法 | 介紹 |
---|---|
void clear() | 清空Map集合中的內容 |
boolean containsKey(Object key) | 判斷集合中是否存在指定的key |
boolean containsValue(Object value) | 判斷集合中是否存在指定的value |
Set<Map,Entry<K,V>> entrySet() | 將Map接口變爲Set集合 |
V get(Object key) | 根據key找到其對應的value |
5.1 HashMap
public class HashMap< K , V > extends AbstractMap< K, V > implements Map < K, V > ,Cloneable,Serializable
基於哈希表的Map接口的實現。此實現提供所有可選的映射操作,並允許使用null值和null鍵。(除了非同步和允許使用null之外,HashMap類與Hashtable大致相同。)此類不保證映射的順序,特別是它不保證該順序恆久不變。
public class MapDemo {
private static void hashMap(){
Map<Integer,String> map = new HashMap<>();
map.put(1,"xx");
map.put(2,"yy");
map.put(3,"zz");
System.out.println("size = "+ map.size());
System.out.println(map.get(1));
//Map的遍歷1 遍歷entry
Set<Entry<Integer,String>> entrySet = map.entrySet();
for(Entry e:entrySet){
System.out.println(e.getKey()+"->"+e.getValue());
}
//Map的遍歷2 遍歷鍵
Set<Integer> keys = map.keySet();
for(Integer i:keys){
String value = map.get(i);
System.out.println(i+"->"+value);
}
//Map的遍歷3 遍歷值
Collection<String> values = map.values();
for(String s :values) {
System.out.println(s);
}
//Map的遍歷4 foreacn
map.forEach((key,value)-> System.out.println(key+"->"+value));
}
public static void main(String[] args) {
hashMap();
}
}
實現原理:
- 基於哈希表(數組+鏈表+二叉樹(紅黑樹))二叉樹是1.8新增的
- 加載因子0.75,默認數組大小爲16
- 對象存儲在哈希表中,把key對象通過hash()方法計算hash值,用此hash值對數組長度取餘(默認16),來決定對key對象在數組中的存儲位置,當這個位置有多個對象時,以鏈表結構存儲,Jdk1.8後,當鏈表長度大於8時,鏈表將轉換爲紅黑樹結構存儲。目的是爲了取值時提高效率,取值更快。存儲的數據量越大,性能的表現越明顯。
- 擴充原理:當數組的容量超過了75%,那麼表示該數組需要擴充。當前數組容量擴大一倍。擴充次數過多會影響性能,每次擴充時哈希表都會重新散列(重新計算每個對象的存儲位置)。
- 線程不安全,適合單線程中使用。
5.2 Hashtable
public class Hashtable< K,V > extends Dictionary< K, V > implements Map< K,V >,Cloneable, Serializable
此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非null對象都可以用作鍵或值。爲了成功地在哈希表中存儲和獲取對象,用作鍵的對象必須實現hashCode方法和equals方法。
Hashtable與HashMap的區別:
- Hashtable 從JDK1.0開始就有了,基於哈希表實現(數組+鏈表),默認數組大小爲11,加載因子0.75,擴充方式爲:原數組擴大一倍並+1。Hashtable是線程安全的,用於多線程。
5.3 LinkedHashMap
Map接口的哈希表和鏈接列表的實現,具有可預知的迭代順序。是HashMap的子類,可以保證順序恆久不變。此類使用一個雙重鏈表來維護元素添加的順序。
5.4 TreeMap
基於紅黑樹的NavigableMap實現。該映射根據其鍵的自然順序進行排序,或者根據創建映射時提供的Comparator進行排序,具體取決於使用的構造方法。
public class MapDemo {
private static void treeMap(){
Map<String,String> table = new TreeMap<>();
table.put("one","lllll");
table.put("two","xxxxx");
table.put("three","bbbbb");
table.forEach((key,value)-> System.out.println(key+"->"+value));
Map<Dog,String> dogs = new TreeMap<>();
dogs.put(new Dog("hhh",2,1),"lllll");
dogs.put(new Dog("hx",5,2),"lll13");
dogs.put(new Dog("hdfh",3,3),"lllll44");
dogs.forEach((key,value)-> System.out.println(key+"->"+value));
}
public static void main(String[] args) {
treeMap();
}
}
public class Dog implements Comparable<Dog>{
private String name;
private int age;
private int id;
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
", id=" + id +
'}';
}
public Dog(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
//。。。getter setter。。。
@Override
public int compareTo(Dog dog) {
return this.id-dog.id;
}
}
5.5 JDK1.8添加的Map接口的新方法
public class MapNewMethodDemo {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"jack");
map.put(2,"tom");
map.put(3,"lily");
//取不到值時,使用默認值
String value = map.getOrDefault(4,"null");
System.out.println(value);
//添加值,只會添加不存在key的值,如果已經存在key,則不會替換
String val = map.putIfAbsent(3,"vince");
System.out.println(val);
//刪除 只有鍵和值都匹配時纔會刪除
map.remove(3,"lily1");
//代替
map.replace(3,"vince");
map.replace(3,"vince","vince1");//只有第一個參數的key,和第二個參數的value匹配,才能替換
//計算,爲給定的key修改value
map.compute(1,(k,v1)->v1+"1");
map.computeIfAbsent(5,(k)->k+"xxx");//如果沒有這個k纔會添加
//合併
map.merge(1,"888",(oldv,newv)->oldv.concat(newv));
//遍歷
map.forEach((k,v)-> System.out.println(k+"->"+v));
}
}
6.Collections工具類
Collections工具類提供了大量針對collection/map的操作,總體可分爲四類,都爲靜態方法。
6.1 排序操作
主要針對list接口
方法 | 介紹 |
---|---|
reverse(List list) | 反轉指定list集合中的元素順序 |
shuffle(List list) | 對list中的元素進行隨機排序(洗牌) |
sort(List list) | 對list裏的元素根據自然升序排序 |
sort(List list,Comparator c) | 自定義比較器排序 |
swap(List list,int i,int j) | 將指定list集合中i處元素和j處元素進行交換 |
rotate(List list,int distance) | 將所有元素向右移位指定長度,如果distance等於size那麼結果不變 |
6.2 查找和替換
主要針對Collection接口
方法 | 介紹 |
---|---|
binarySerach(List list,Object key) | 使用二分搜索,獲取指定對象在list中的索引,前提是集合已經排序 |
max(Collection coll) | 返回最大元素 |
max(Collection coll, Comparator comp) | 根據自定義比較器,返回最大元素 |
min(Collection coll) | 返回最小元素 |
min(Collection coll, Comparator comp) | 根據自定義比較器,返回最小元素 |
fill(List list,Object obj) | 使用指定對象填充 |
frequency(Collection coll,Object o) | 返回指定集合中指定對象出現的次數 |
replaceAll(List list,Object old,Object new) | 替換 |
6.3 同步控制
Collections 工具類中提供了多個synchronizedXxx方法,該方法返回指定集合對象對應的同步對象,從而解決多線程併發訪問集合時線程的安全問題。HashSet、ArrayList、HashMap都是線程不安全的,如果需要考慮同步,則使用這些方法:synchronizedSet, synchronizedSortSet, synchronizedList, synchronizedMap, synchronizedSortMap。需要注意的是,在使用迭代方法遍歷集合時,需要手工同步返回的集合。
6.4 設置不可變集合
Collections 有三類方法可以返回一個不可變集合:
方法 | 介紹 |
---|---|
emptyXxx() | 返回一個空的不可變的集合對象 |
singletonXxx() | 返回一個只包含指定對象的,不可變的集合對象 |
unmodifiableXxx() | 返回指定集合對象的不可變視圖 |
6.5 其他
方法 | 介紹 |
---|---|
disjoint(Collection< ? > c1, Collection< ? > c2 ) | 如果指定collection中沒有相同的元素,則返回true |
addAll(Collection< ? super T > c, T … a) | 一種方便的方式,將所有指定元素添加到指定collection中 |
Comparator< T > reverseOrder (Comparator < T > cmp) | 返回一個比較器,它強行反轉指定比較器的順序。如果指定比較器爲null,則此方法等同於reverseOreder()。(換句話說,它返回一個比較器,該比較器將強行反轉實現Comparable接口那些對象Collection上的自然順序) |
public class CollectionsDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("xxx");
list.add("yyy");
list.add("zzz");
//排序
// Collections.reverse(list);
// Collections.shuffle(list);
// Collections.sort(list);
// Collections.swap(list,0,2);
// Collections.rotate(list,1);
//查找和替換
// System.out.println(Collections.binarySearch(list,"yyy"));
// System.out.println(Collections.max(list));
// System.out.println(Collections.min(list));
// Collections.fill(list,"bin");
// System.out.println(Collections.frequency(list,"xxx"));
// Collections.replaceAll(list,"xxx","bin");
//同步控制
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
//設置不可變集合,
// List<String> slist = Collections.emptyList();
// slist.add("bing");//會拋出異常,不可添加
//這個不可變的空list可以用於方法返回值,在方法調用後得到的結果通過size來判斷是否有值,而不需要判斷是否爲空。
/*比如:
public static List<String> count(){
List<String> list = null;
if(....==null){
return Collections.emptyList();
}
}
List<String> li = count():
if(li.size()==0){
//....
}
*/
//反轉排序
Collections.sort(list,Collections.reverseOrder());
System.out.println("-------");
list.forEach(System.out::println);
}
}
7.Optional容器類(JDK1.8)
Opational容器類是一個可以爲null的容器對象。如果值存在則isPresent()方法會返回true,調用get()方法會返回該對象
方法 | 介紹 |
---|---|
of | 爲非null的值創建一個Optional |
ofNullable | 爲指定的值創建一個Optional,如果指定的值爲null,則返回一個空的Optional |
isPresent | 如果值存在則返回ture,否則false |
get | 如果Optional有值,則將其返回,否則拋出NoSuchElementException |
ifPresent | 如果Optional實例有值,則爲其調用consumer,否則不做處理 |
orElse | 如果有值將其返回,否則返回他的指定值 |
orElseGet | 與orElse類似,區別在於得到的默認值。orELse將傳入的字符串作爲默認值,orElseGet可以接受Supplier接口的實現用來生成默認值 |
orElseThrow | 如果有值則將其返回,否則拋出supplier接口創建的異常 |
map | 如果有值,則對其執行調用mapping函數得到返回值,如果返回值不爲null,則創建包含mapping返回值的Optional作爲map方法返回值,否則返回空optional |
flatMap | 如果有值,爲其執行mapping函數返回optional類型返回值,否則返回空optional。flatMap與map方法類似,區別在於flatMap中的mapper返回值必須是optional。調用結束時,flatMap不會對結果用optional封裝。 |
filter | 如果有值並且滿足斷言條件,返回包含該值的optional,否則返回空optional |
public class OpationalDemo {
public static void main(String[] args) {
//創建方式
Optional<String> opt = Optional.of("bin");
// Optional<String> opt1 = Optional.ofNullable("bin");
Optional<String> opt2 = Optional.empty();
System.out.println(opt.isPresent());
System.out.println(opt.get());
opt.ifPresent((value)-> System.out.println(value));
System.out.println(opt2.orElse("沒有值"));
System.out.println(opt2.orElseGet(()->"default"));
// try {
// opt2.orElseThrow(Exception::new);
// } catch (Exception e) {
// e.printStackTrace();
// }
Optional<String> opt3 = opt.map((value)->value.toUpperCase());
System.out.println(opt3.orElse("no value"));
Optional<String> opt4 = opt.flatMap((value)->Optional.of(value.toUpperCase()));
System.out.println(opt4.orElse("no value"));
Optional<String> opt5 = opt.filter((v)->v.length()>3);
System.out.println(opt5.orElse("小於3"));
}
}
/*
true
bin
bin
沒有值
default
BIN
BIN
小於3
Process finished with exit code 0
*/
8.Queue和Deque
隊列(Queue)是一種特殊的線性表,先進先出,只允許在表的前端(front,隊頭)進行刪除操作,在表的後端(rear,隊尾)進行插入操作。隊列中沒有元素時,稱爲空隊列。
LinkedList是Queue接口的實現類
方法 | 介紹 |
---|---|
boolean add(E e) | 向隊列插入元素,成功時返回true,如果沒有可用的空間,則拋出IllegalStateException |
E element() | 獲取但不移除隊頭元素 |
boolean offer(E e) | 向隊列插入元素,成功時返回true,此方法優於add(E) |
E peek() | 獲取但不移除隊頭元素,若隊列爲空則返回null |
E poll() | 獲取並移除隊頭元素,若隊列爲空則返回null |
E remove() | 獲取並移除隊頭元素 |
Deque: 一個線性collection,支持在兩端插入和移除元素。
此接口既支持有容量限制的雙端隊列,也支持沒有固定大小限制的雙端隊列。接口定義在雙端隊列兩端訪問元素的方法,提供插入,移除和檢查元素的方法。
public class QueueDequeDemo {
private static void queue(){
Queue<String> queue = new LinkedList<>();
queue.add("xxx");
queue.add("yyy");
queue.add("zzz");
System.out.println(queue.size());
System.out.println(queue.peek());
System.out.println(queue.size());
System.out.println(queue.poll());
System.out.println(queue.size());
}
private static void deque(){
Deque<String> deque = new LinkedList<>();
deque.add("xxx");
deque.add("yyy");
deque.add("zzz");
System.out.println(deque.size());
System.out.println(deque.getFirst());
System.out.println(deque.getLast());
}
public static void main(String[] args) {
deque();
}
}