第五節 Java 集合
- 1. 集合概述
-
- 1.1 數組與集合之間的差別
- 1.2 集合的分類
- 2. Collection接口
- 3. List接口
-
- 3.1 ArrayList 集合
- 3.2 LinkedList 集合
- 3.3 Vector集合
- 4. Collection 集合周遊
-
- 4.1 通過Iterator進周遊
- 4.2 通過增強for來進行周遊
- 4.3 通過集合的forEach(Consumer action)方法來周遊
- 4.4 通過疊代器的forEachRemaining(Consumer action)方法來進行周遊
- 4.5 通過for循環來進行周遊
- 5. Set 接口
-
- 5.1 HashSet 集合
- 5.2 TreeSet 集合
- 6. Map 接口
-
- 6.1 HashMap 集合
- 6.2 Map 集合的周遊
- 6.3 LinkedHashMap 集合
- 6.4 TreeMap 集合
- 6.5 Properties 集合
- 7. 泛型
- 8. 常用工具類
-
- 8.1 Collections 工具類
- 8.2 Arrays 工具類
- 9. 聚合操作
-
- 9.1 建立Stream流對象的幾種方式
- 9.2 Stream流常用方法
- 9.3 Parallel Stream(并行流)
1. 集合概述
1.1 數組與集合之間的差別
集合主要是用來解決數組的一些缺陷,比如數組的長度不能夠自動的根據内容的添加去自動的去增加長度,一旦數組的長度定下來就不會變了,這樣有時候會發現我們定義的長度不夠,或者定義的長度過長導緻記憶體使用率降低,而集合是一個長度可變的容器,他會自動的根據我們的添加和删除去自動的給我們增加或添加空間。但是,集合的速度不如數組的快(在有些時候),但又各有優點。是以在選擇的時候可以根據需要去進行選擇。
1.2 集合的分類
這些集合都位于java.util包中。按存儲結構我們可以分為兩類單列集合Collection和雙列集合Map。
(1)對于單列集合:Collection集合有兩個重要的子接口,分别是List和Set。List集合的特點就是元素有序(存入順序和取出順序一緻),可重複。對于Set集合元素無序且不可重複。List的主要實作類有ArrayList和LinkedList;Set主要的實作類有HashSet和TreeSet。
(2)對于雙列集合:Map用于存儲具有鍵值映射關系的元素,主要的實作類有HashMap和TreeMap。
虛框是接口,實框是實作類。
2. Collection接口
這裡面的方法是單列集合的通用方法,主要方法有如下:
方法聲明 | 功能描述 |
---|---|
boolean add(Object o) | 向集合中添加一個元素 |
boolean addAll(Collection c) | 将指定集合c中的元素添加到該集合 |
void clear() | 删除該集合中所有的元素 |
boolean remove(Object o) | 删除該集合中指定的元素 |
boolean removeAll(Collection c | 删除指定集合c中元素 |
boolean isEmpty() | 判斷集合是否為空 |
boolean contains(Object o) | 判斷集合是否包含某個元素 |
boolean containsAll(Collection c) | 判斷集合是否包含指定集合c中的元素 |
Iterator iterator() | 傳回該集合的元素上進行疊代的疊代器 |
int size() | 擷取該集合元素個數 |
Stream<E> stream() | 将集合源轉換為有序元素的流對象 |
3. List接口
List接口常用方法:
方法聲明 | 功能描述 |
---|---|
void add(int index,Object element) | 将元素element插入集合指定索引 |
boolean addAll(int index,Collention c) | 将集合c包含的所有元素插入指定索引位置處 |
Object get(int index) | 傳回指定索引處的元素 |
Object remove(int index) | 删除索引處的元素 |
Object set(int index,Object element) | 将索引處元素替換成element,并傳回被替換的元素 |
int indexOf(Object o) | 傳回對象o在List集合首次出現的索引 |
int lastIndexOf(Object o) | 傳回對象o在List集合最後一次出現位置處的索引 |
List subList(int fromIndex,int toIndex) | 傳回從fromIndex到toIndex(不包括)的List的子集 |
Object[ ] toArray() | 将集合元素轉換為數組 |
default void sort(Comparator<? super E> c) | 根據指定的比較器規則對集合元素排序 |
3.1 ArrayList 集合
底層是由數組實作的,在增加或删除指定位置元素時效率比較低,但是在進行查詢的時候比較快,它封裝了一個變長的數組,當存入元素超過數組長度,ArrayList會在記憶體中配置設定一個更大的數組來存儲這些元素。
3.2 LinkedList 集合
LinkedList集合它的底層是由雙向循環連結清單實作的。是以在進行增删的時候效率比較高,但是查詢效率不高。是以在選擇時我們要根據我們要對數組進行怎麼樣的操來進行選擇。
在LinkedList集合中有一些特有的方法:、
方法聲明 | 功能描述 |
---|---|
boolean add(int index,Object element) | 将元素插入指定位置 |
void addFirst(Object o) | 在集合開頭插入元素 |
void addLast(Object o) | 在集合結尾添加元素 |
Object getFirst() | 傳回集合第一個元素 |
Object getLast() | 傳回集合中的最後一個元素 |
Object removeFirst() | 移除并傳回集合中的第一個集合 |
Object removeLast() | 移除并傳回集合中的最後一個集合 |
boolean offer(Object o) | 将指定元素添加到集合結尾 |
boolean offerFirst(Object o) | 将指定元素添加到集合開頭 |
boolean offerLast(Object o) | 将指定元素添加到集合的結尾 |
Object peek() | 擷取集合第一個元素 |
Object peekFirst() | 擷取集合第一個元素 |
Object peekLast() | 擷取集合最後一個元素 |
Object poll() | 移除并傳回集合的第一個元素 |
Object pollFirst() | 移除并傳回集合的第一個元素 |
Object pollLast() | 移除并傳回集合最後一個元素 |
Object push(Object o) | 将指定元素添加到集合開頭 |
Object pop() | 移除并傳回集合的第一個元素 |
3.3 Vector集合
這是相當于老版本ArrayList集合,不過它加了很多的同步,是以它相對的比較的安全。
4. Collection 集合周遊
4.1 通過Iterator進周遊
方式如下:
public class IteratorDemo {
public static void main(String[] args) {
ArrayList<String> textArray=new ArrayList<String>();
textArray.add("iteratored1");
textArray.add("iteratored2");
Iterator iterator=textArray.iterator();
while(iterator.hasNext()){
String text= (String) iterator.next();
System.out.println(text);
}
}
}
結果如下:
但在這裡周遊時不能對元素進行删除和添加操作,否則它的指針找不到對應位置會報錯的。就好比,Iterator已經記好了它要周遊的每個元素對應的村粗空間,但是這時,你對裡面的元素删除了,這樣他指向下一個指針的時候這個空間可能就會在記憶體中顯示空閑,這樣就會報錯。
這裡有以下兩種解決辦法:
(1)如果從業務邏輯上我們隻是單單删除某個元素然後跳出不再進行疊代是可以的,比如我們用,if(“iteratored2”.equals(text)){textArray.remove(text);break;}
(2)我們不通過集合的remove去删除,我們 通過疊代器自帶的remove()方法來進行删除,比如我們在循環内部這樣使用,if(“iteratored2”.equals(text)){iterator.remove();}
4.2 通過增強for來進行周遊
文法格式如下:
for(容器中元素類型 臨時變量:容器變量){執行語句}
具體用法如下:
public class ForDemo {
public static void main(String[] args) {
ArrayList<String> array=new ArrayList<String>();
array.add("test1");
array.add("test2");
for(String obj:array){
System.out.println(obj);
}
}
}
結果如下:
這種方法比較簡潔,但是也有它的一定局限性,這種方法隻能對集合元素進行通路不能對其中的元素進行修改。
比如我們想将String[ ] strs={“aaa”,“bbb”,“ccc”};裡面的所有元素修改成ddd,我們不能通過for(String str :strs){str=“ddd”}的方法來進行,因為這隻是将臨時變量str指派了一個ddd,并沒有對strs進行修改。
4.3 通過集合的forEach(Consumer action)方法來周遊
這是JDK 8之後才有的方法,這個方法需要的參數是一個函數式接口。
具體的使用方法如下:
public class ForEachDemo {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<String>();
list.add("秀兒");
list.add("是你嘛");
list.forEach(str-> System.out.println("疊代集合元素:"+str));
}
}
結果如下圖:
4.4 通過疊代器的forEachRemaining(Consumer action)方法來進行周遊
使用方法如下:
public class ForEachRemainingDemo {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<String>();
list.add("通過疊代器的forEachRemaining方法來進行周遊");
list.add("周遊完了");
//将集合轉換成疊代器對象
Iterator it=list.iterator();
it.forEachRemaining(str-> System.out.println(str));
}
}
結果如下圖:
4.5 通過for循環來進行周遊
使用方法如下:
public class Forxunhuan {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<String>();
list.add("forxunhuan");
list.add("bianli");
for (int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
}
結果如下圖:
5. Set 接口
Set接口主要的實作類為:HashSet,TreeSet,其中HashSet根據對象的哈希值來确定元素在集合中存儲的位置,是以它比較的容易查找和存取,TreeSet是通過二叉樹的方式來進行元素的存儲,它可以實作對集合中的元素進行排序。
5.1 HashSet 集合
當我們向HashSet集合中添加一個元素時,首先會調用該元素的hashCode()方法來确定元素的存儲位置,然後再調用對象的equals()方法來確定這個位置沒有重複元素。
注意:為了保證我們的HashSet集合可以正常的工作,當我們存入的是我們自定義的對象時,我們需要重寫hashCode()方法和equals()方法,如果不是自定義的對象,他們的hashCode()和equals()方法都已經被重新二過了。
例如如下:
public class Student {
String id;
String name;
public Student(String id,String name){
this.id=id;
this.name=name;
}
//重寫toString()方法
public String toString(){
return id+":"+name;
}
//重寫hashCode()方法
public int hashCode(){
return id.hashCode();
}
//重寫equals()方法
public boolean equals(Object obj){
if(this==obj){
return true;
}
if(!(obj instanceof Student)){
return false;
}
Student stu=(Student) obj;
boolean b=this.id.equals(stu.id);
return b;
}
}
public class Example01 {
public static void main(String[] args) {
HashSet hs=new HashSet();
Student stu1=new Student("01","san");
Student stu2=new Student("02","si");
hs.add(stu1);
hs.add(stu2);
System.out.println(hs);
}
}
結果如下:
5.2 TreeSet 集合
内部采用平衡二叉樹來存儲元素,這樣可以保證TreeSet集合中沒有重複的元素,并且對元素進行排序。所謂二叉樹就是每個節點最多有兩個子節點的有序樹,每個節點的左邊叫左子樹,右邊叫右子樹,其中左子樹小于它的根節點,右子樹大于它的根節點。
TreeSet集合中一些特有方法如下:
public class TreeSetDemo {
public static void main(String[] args) {
//建立TreeSet集合
TreeSet ts=new TreeSet();
ts.add(3);
ts.add(5);
ts.add(11);
ts.add(8);
System.out.println("建立的TreeSet集合為:"+ts);
//獲得集合中的首尾元素
System.out.println("集合首元素為:"+ts.first());
System.out.println("集合末尾元素為:"+ts.last());
//比較并擷取元素
System.out.println("lower()方法,傳回小于5的最大元素:"+ts.lower(5));
System.out.println("floor()方法,傳回小于或等于5的最大元素:"+ts.floor(5));
System.out.println("higher()方法,傳回大于5的最小元素:"+ts.higher(5));
System.out.println("ceiling()方法,傳回大于或等于5的最小元素:"+ts.ceiling(5));
//移除并傳回
System.out.println("移除并傳回第一個元素:"+ts.pollFirst());
System.out.println("移除并傳回最後一個元素:"+ts.pollLast());
}
當我們存入元素的時候首先會和根節點進行比較如果小于根節點,就和根節點左邊的繼續進行比較,如果大于根節點就和根節點右邊的進行比較,以此類推一直比較到最後一個節點如果沒有重複的,小于最後一個節點就放最後一個節點的左邊,大于了就放最後一個節點的右邊。在這裡我們一般的對象都重寫了Comparable裡面的compareTo()方法,當我們存入的時候就會調用這個方法進行比較,但是我們在開發中可能會存入一些我們自定義的對象,這時候我們就需要重新制定排序規則。為了解決這個問題Java提供了兩種方法
(1)自然排序
這裡要求向TreeSet集合中存儲的元素所在的類必須實作Comparable接口,并重寫compareTo()方法,然後TreeSet集合就會對該類型元素使用compareTo()方法進行比較,并預設進行升序。
使用如下:
public class Teacher implements Comparable{
String name;
int age;
public Teacher(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return name+":"+age;
}
//重寫CompareTo()方法
public int compareTo(Object obj){
Teacher s=(Teacher) obj;
//按照年齡來進行升序
if (this.age-s.age>0){//将this.age和s.age互換就變成降序
return 1;
}
if(this.age-s.age==0){
return this.name.compareTo(s.name);//如果年齡相同,我們就用name來進行比較
}
return -1;
}
}
public class ComparableDemo {
public static void main(String[] args) {
TreeSet ts=new TreeSet();
ts.add(new Teacher("Jack",19));
ts.add(new Teacher("Rose",18));
ts.add(new Teacher("Tom",19));
ts.add(new Teacher("Rose",18));
System.out.println(ts);
}
}
結果如下:
(2)定制排序
用來當我們不想按照定義的compareTo()方法進行排序,比如我們希望可以按照字元串的長度,而不是英文字母順序來進行排序,我們可以通過在建立TreeSet集合的時候就定義一個比較器往構造裡面傳入自定義的比較器來進行定制排序。
例如:
public class MyComparator implements Comparator {
@Override
public int compare(Object obj1, Object obj2) {//定制排序
String s1=(String)obj1;
String s2=(String)obj2;
int temp=s1.length()-s2.length();
return temp;
}
}
public class ComparatorDemo {
public static void main(String[] args) {
TreeSet ts=new TreeSet(new MyComparator());
ts.add("Java");
ts.add("Python");
ts.add("C++");
System.out.println(ts);
}
}
結果如下:
從上面的程式可以看出,我們需要寫排序,根據某個值,是以我們在向TreeSet裡面存入資料的時候我們要保證是同一種資料類型,不然會報錯,是以這裡就用到了我們的泛型。
6. Map 接口
在Map裡面鍵是唯一的,鍵值對一一對應。
Map常用的方法:
方法說明 | 功能描述 |
---|---|
void put(Object key,Object value) | 向Map集合中添加指定鍵值映射元素 |
int size() | 傳回集合中鍵值對的個數 |
Object get(Object key) | 傳回指定鍵所映射的值,若沒有傳回null |
Object getOrDefault(Object key,Object DefaultValue) | 傳回指定鍵對應的值,不存在預設傳回default。 |
boolean containsKey(Object key) | 判斷集合中是否存在這個鍵 |
boolean containsValue(Object value) | 判斷集合中是否存在這個值 |
Object remove(Object key) | 移除指定鍵的鍵值對。 |
void clear() | 清空整個Map集合中的鍵值映射元素 |
Set keySet() | 以Set集合的形式傳回Map集合中所有的key對象 |
Collection values() | 以Collection集合的形式傳回Map集合中所有值對象 |
Set<Map.Entry<Key,Value>> entrySet() | 将Map集合轉換為存儲類型為Map的Set集合 |
void forEach(BiConsumer action) | 通過傳入一個函數式接口,對Map集合元素進行周遊 |
Object putIfAbsent(Object key,Object value) | 向Map集合中添加指定鍵值映射,如果已經存在就不再添加了,傳回已存在的Value值 |
boolean remove(Object key,Object value) | 删除鍵值對同時比對的元素 |
boolean replace(Object key,Object value) | 将Map集合中指定鍵對象所映射的值改為value |
6.1 HashMap 集合
HashMap是Map的一個實作類,鍵和值允許為空,但是鍵不能重複,且集合中的元素是無序的。它的底層是由數組+連結清單來實作的。連結清單主要是用來解決哈希沖突的。結構上水準方向數組的長度稱為HashMap的容量,豎直方向每個元素位置對應的連結清單結構稱為一個桶,每個桶的位置在集合中都有對應的桶值,當我們向集合中添加元素時,首先會調用鍵對象的hash(k)方法尋找到該元素要存儲的位置,如果這個位置為空,那麼就直接放到集合内,如果這個位置不為空,那麼就需要來比較已經存在的k與要添加進去的元素的k值是否相同,如果相同就将原來k對應的值修改為新的k對應的值,如果不相同,就會在這個桶的連結清單結構頭部新增一個節點來插入新元素對象。
HashMap中桶數量配置設定政策:
在我們建立HashMap之後,會預設集合的容量capacity為16,加載因子loadFactor為0.75,此時改集合桶的門檻值就為12,當添加的元素超過12之後,HashMap就會預設增加一倍的桶數量,如果開發中想節省一點空間可以通過它的構造方法來設定桶初始容量和加載因子。new HashMap(int initialCapacity,float loadFactor)
6.2 Map 集合的周遊
(1)通過疊代器周遊Map
第一種:使用如下:
public class MapDemo01 {
public static void main(String[] args) {
Map map=new HashMap();
map.put("1","Jack");
map.put("2","Rose");
map.put("3","Lucy");
System.out.println(map);
Set keySet=map.keySet();
Iterator it=keySet.iterator();
while(it.hasNext()){
String key=(String)it.next();
String value=(String)map.get(key);
System.out.println(key+":"+value);
}
}
}
結果如下圖:
第二種:通過entrySet()方法擷取
public class MapDemo03 {
public static void main(String[] args) {
Map map=new HashMap();
map.put("1","Jack");
map.put("2","Rose");
map.put("3","Lucy");
System.out.println(map);
Set entrySet=map.entrySet();
Iterator it=entrySet.iterator();
while(it.hasNext()){
Map.Entry entry=(Map.Entry)it.next();
Object key=entry.getKey();
Object value=entry.getValue();
System.out.println(key+":"+value);
}
}
}
(2)通過Map裡面的forEach(BiConsumer action)方法進行周遊
public class MapDemo02 {
public static void main(String[] args) {
Map map=new HashMap();
map.put("1","Jack");
map.put("2","Rose");
map.put("3","Lucy");
System.out.println(map);
map.forEach((key,value)-> System.out.println(key+":"+value));
}
}
(3)直接使用Map提供的values()方法直接擷取值對象的Collection。剩下的周遊方式與單列集合一樣。
6.3 LinkedHashMap 集合
我們使用HashMap時不能保證集合中元素存入和取出的順序,而使用LinkedHashMap類可以保證,他是HashMap的子類,它使用雙向連結清單來維護内部關系。是以當我們需要存入的和取出的順序相同我們就可以用LinkedHashMap類。
6.4 TreeMap 集合
同TreeSet一樣,他底層也是用二叉樹來實作的,用二叉樹的方式來確定鍵的唯一。使用如TreeSet類似。如果要存入自定義的鍵類型,那麼就需要自定義類型去實作Comparable并重寫compareTo()方法或自定義進行排序,在構造的時候傳入自定義類。
6.5 Properties 集合
他是HashTable的子類。和HashMap十分相似,不同的是Hashtable是線程安全的。但是Hashtable效率要比Hashtable高。是以基本被HashMap取代,它有一個子類Properties,主要用來存放字元串類型的鍵值。實際開發中經常使用Properties集合類來存取應用的配置項。
使用方法如下:
public class MapDemo04 {
public static void main(String[] args) throws IOException {
//1.通過Properties進行屬性檔案讀取操作
Properties pps=new Properties();
//加載要讀取的檔案
pps.load(new FileInputStream("test.properties"));
//周遊
pps.forEach((key,value)-> System.out.println(key+":"+value));
//通過Properties進行屬性檔案的寫入
FileOutputStream out=new FileOutputStream("test.properties");
pps.setProperty("charset","UTF-8");
pps.store(out,"新增charset編碼");
}
}
結果如下:
7. 泛型
用來解決集合中元素存取安全的,我們都知道我們可以任意的向集合中去存取任意類型的元素,但是當我們去取出時候,我們可能就不确定我們取出來的是什麼類型的,這樣當我們進行強制轉換的時候可能就會出現錯誤。
具體使用格式如下:
ArrayList<參數化類型> list=new ArrayList<參數化類型>();
用這種方式來規定我們存入的必須是某種參數類型,這樣就保證了在取出時候的類型。如果我們存入的類型不是參數化類型,在進行編譯的時候就會報錯。一定程度上保證了程式的健壯性和安全性。
注意:集合中如果我們沒有規定參數化類型,預設我們存入的都是Object類型的。
8. 常用工具類
8.1 Collections 工具類
(1)對于List集合的常用添加和排序方法
方法聲明 | 功能描述 |
---|---|
static <T> boolean addAll(Collection <? super T> c,T …elements) | 将所有元素添加到集合c中 |
static void reverse(List list) | 反轉指定List集合中的元素順序 |
static void shuffle(List list) | 對List集合中的元素進行随機排序 |
statci void sort(List list) | 根據元素的自然順序對集合List集合中的元素進行排序 |
static void swap(List list,int i,int j) | 将指定List集合中的角标i處元素和j處元素進行交換 |
(2)查找和替換操作
方法聲明 | 功能描述 |
---|---|
static int binarySearch(List list Object key) | 使用二分搜尋法來找指定集合中的指定元素的索引,List集合中元素必須有序 |
static Object max(Collection col) | 找到集合中最大元素并傳回 |
static Object min(Collection col | 找到集合中最小的元素并傳回 |
static boolean replaceAll(List list,Object oldVal,Object newVal) | 用一個新值替換集合中所有舊值oldVal |
8.2 Arrays 工具類
這個類主要針對數組進行操作。
(1)靜态方法sort()用來對數組進行排序
(2)靜态方法binarySearch(Object[ ] a,Object key)查找元素索引,使用這個方法前提要先對數組進行排序。
(3)靜态方法copyOfRange(int[ ] original,int from ,int to)拷貝元素
這個方法可以在不破壞原數組的情況下拷貝部分元素到新數組中。from表示拷貝開始的索引,to表示拷貝結束的索引(不包括本身)
(4)靜态方法fill(Object[ ] a, Object val)将數組中所有元素替換為一個元素。
9. 聚合操作
主要目的簡化代碼量,提高執行效率。
JDK 8增加了一個Stream接口,通過它将集合和數組轉換為Stream流形式,并結合Lambda表達式的優勢進一步簡化集合、數組中元素查找、過濾、轉換等操作。
聚合操作的使用步驟:
(1)将原始集合或數組轉換為Stream流
(2)對Stream流對象中的元素進行一系列的過濾、查找等中間操作,仍傳回一個Stream流對象
(3)對Stream流進行周遊
統計、收集等終結操作。
使用方式如下:
public class Juhecaozuo {
public static void main(String[] args) {
//建立List對象
List<String> list=new ArrayList<>();
list.add("張三");
list.add("李四");
list.add("張小明");
list.add("張陽");
//第一步:轉換為Stream流
Stream<String> stream=list.stream();
//第二步:進行操作
Stream<String> stream1=stream.filter(i->i.startsWith("張"));
//第三步:終結操作
stream1.forEach(j-> System.out.println(j));
//通過鍊式一步到位
System.out.println("============");
list.stream().filter(i->i.startsWith("張")).forEach(j-> System.out.println(j));
}
}
注意:我們在進行流操作的時候不會改變源數組或集合中的資料,我們隻是改變了流對象中的資料。
9.1 建立Stream流對象的幾種方式
(1)所有的Colections集合都可以使用stream()靜态方法擷取Stream流
(2)Stream接口的of()靜态方法可以擷取基本類型包裝類數組、引用類型數組和單個元素的Stream流對象
(3)Arrays數組工具類的stream()靜态方法擷取。
如下:
public class StreamDemo {
public static void main(String[] args) {
//建立一個數組
Integer[] array={9,8,3,5,2};
//将數組轉換為List集合
List<Integer> list= Arrays.asList(array);
//使用集合的stream()靜态方法擷取Stream流
Stream<Integer> stream=list.stream();
stream.forEach(i-> System.out.print(i+" "));
System.out.println();
//2.使用Stream接口的靜态方法of()擷取Stream流
Stream<Integer> stream1=Stream.of(array);
stream1.forEach(i-> System.out.print(i+" "));
System.out.println();
//使用Arrays工具類的stream()靜态方法擷取Stream流
Stream<Integer> stream2=Arrays.stream(array);
stream2.forEach(i-> System.out.print(i+" "));
}
}
對于Map我們需要先将其變成單列集合在用單列集合的stream()方法來擷取Stream流
9.2 Stream流常用方法
方法聲明 | 功能描述 |
---|---|
Stream<T> filter(Predicate<?super T> predicate) | 将指定流對象的元素進行過濾并傳回一個流對象 |
Stream<R>map(Function<?super T, ?extends R> mapper) | 将流中元素按照一定規則映射到另一個流中 |
Stream<T> distinct() | 删除流中重複元素 |
Stream<T> sorted() | 将流中對象按自然順序排序 |
Stream<T> limit(long maxSize) | 截取流中元素的長度 |
Stream<T> skip(long n) | 丢棄流中前n個元素 |
static<T> Stream <T> concat(Stream<?extendsT>a,Stream<?extends T> b) | 将兩個流合并為一個流 |
long count() | 統計流中的元素個數 |
R collect(Collector<?super T,A,R> collector) | 将流中元素收集到一個容器中(如集合) |
Object[ ] toArray() | 将流中的元素收集到一個數組中 |
void forEach() | 對流中元素進行周遊 |
例如映射的使用:
public class MapMethDemo {
public static void main(String[] args) {
Stream<String> stream=Stream.of("a1","a2","b1","c2","c1");
stream.filter(s->s.startsWith("c"))
.map(String::toUpperCase)
.sorted().forEach(System.out::println);
}
}
收集的使用:
public class CollectDemo {
public static void main(String[] args) {
//建立一個Stream流
Stream<String> stream=Stream.of("張三","李四","張小明","張陽");
//通過filter()方法篩選以張字開頭的怨怒是,通過collect進行收集到集合中
List<String> list=stream.filter(i->i.startsWith("張")).collect(Collectors.toList());
System.out.println(list);
//篩選後收集到字元串中
Stream<String> stream1=Stream.of("張三","李四","張小明","張陽");
String str=stream1.filter(i->i.startsWith("張")).collect(Collectors.joining("-"));
System.out.println(str);
}
}
注意:流一旦執行完終結操作,那麼這個流就不複存在了。
9.3 Parallel Stream(并行流)
将源資料分為多個子流對象進行多線程操作(也就是多個管道流),然後将處理結果再彙總為一個流對象。這樣效率會提升,但是同時帶來安全性問題。
建立并行流的兩種方法:
(1)通過Collection接口的parallelStream()方法變成并行流
(2)通過BaseStream接口的parallel()方法将串行流轉換為并行流。
注意:不管是并行流還是串行流都擁有相同的方法。
建立方法如下:
public class ParallelStremDemo {
public static void main(String[] args) {
List<String> list= Arrays.asList("張三","李四","張小明","張陽");
//直接用Collection接口中的parallelStream()方法
Stream<String> parallelStreamstream=list.parallelStream();
System.out.println(parallelStreamstream.isParallel());
//使用BaseStream裡面的parallel()方法
Stream<String> stream=Stream.of("張三","李四","張小明","張陽");
Stream<String> parallelStream2=stream.parallel();
System.out.println(parallelStream2.isParallel());
}
}