40个Java Collections面试问答
Java Collections Framework是Java編程語言的基本方面。 這是Java面試問題的重要主題之一。 在這里,我列出了Java集合框架的一些重要問題和解答。
Java Collections面試問題答案
列出Collections框架的一些好處?
每種編程語言都使用集合,并且最初的Java版本包含幾個集合類: Vector , Stack , Hashtable和Array 。 但是從更大的范圍和用法來看,Java 1.2提出了Collections Framework,該框架將所有collections接口,實現(xiàn)和算法分組。 Java集合通過使用泛型和并發(fā)集合類進行線程安全操作已經(jīng)走了很長一段路。 它還包括在Java并發(fā)包中的阻塞接口及其實現(xiàn)。 收款框架的一些好處是:
- 通過使用核心集合類而不是實現(xiàn)我們自己的集合類來減少開發(fā)工作。
- 通過使用經(jīng)過良好測試的集合框架類,可以提高代碼質(zhì)量。
- 通過使用JDK附帶的收集類,減少了代碼維護工作。
- 可重用性和互操作性
集合框架中泛型的好處是什么?
Java 1.5帶有泛型,所有集合接口和實現(xiàn)都大量使用它。 泛型允許我們提供集合可以包含的Object的類型,因此,如果您嘗試添加其他類型的任何元素,則會引發(fā)編譯時錯誤。 這樣可以避免在運行時發(fā)生ClassCastException,因為您將在編譯時收到錯誤。 由于我們不需要使用強制轉(zhuǎn)換和instanceof運算符,因此泛型也使代碼更干凈。 由于不會生成進行類型檢查的字節(jié)碼指令,因此它還可以增加運行時的收益。
Java Collections Framework的基本接口是什么?
集合是集合層次結(jié)構(gòu)的根。 集合表示一組稱為其元素的對象。 Java平臺不提供此接口的任何直接實現(xiàn)。
Set是一個不能包含重復元素的集合。 此接口對數(shù)學集合的抽象進行建模,并用于表示集合,例如紙牌組。
List是一個有序的集合,可以包含重復的元素。 您可以從索引中訪問任何元素。 列表更像是具有動態(tài)長度的數(shù)組。
映射是將鍵映射到值的對象。 映射不能包含重復的鍵:每個鍵最多可以映射到一個值。
其他一些接口是Queue , Dequeue , Iterator , SortedSet , SortedMap和ListIterator 。
為什么Collection不擴展Cloneable和Serializable接口?
集合接口指定一組稱為元素的對象。 元素的維護方式取決于Collection的具體實現(xiàn)。 例如,某些Collection實現(xiàn)(例如List)允許重復元素,而其他實現(xiàn)(例如Set)則不允許重復元素。 許多Collection實現(xiàn)都有公共克隆方法。 但是,將其包含在Collection的所有實現(xiàn)中并沒有任何意義。 這是因為Collection是抽象表示。 重要的是實施。
在處理實際實現(xiàn)時,克隆或序列化的語義及其含義都會發(fā)揮作用。 因此具體的實現(xiàn)應決定如何克隆或序列化它,甚至可以對其進行克隆或序列化。 因此,在所有實現(xiàn)中強制進行克隆和序列化實際上不太靈活,而且限制更大。 具體實現(xiàn)應決定是否可以克隆或序列化。
為什么Map界面不擴展Collection界面?
盡管Map接口及其實現(xiàn)是Collections Framework的一部分,但Map不是集合,集合也不是Map。 因此,Map擴展Collection是沒有意義的,反之亦然。
如果Map擴展了Collection接口,那么元素在哪里? Map包含鍵值對,并且提供了一些方法來檢索鍵或值的列表作為Collection,但它不適合“元素組”范式。
什么是迭代器?
迭代器接口提供了對任何Collection進行迭代的方法。 我們可以使用迭代器方法從Collection中獲取迭代器實例。 在Java Collections Framework中,迭代器代替了枚舉。 迭代器允許調(diào)用者在迭代過程中從基礎(chǔ)集合中刪除元素。
Enumeration和Iterator接口之間有什么區(qū)別?
枚舉的速度是Iterator的兩倍,并且使用的內(nèi)存更少。 枚舉是非常基本的,適合基本需求。 但是,與Enumeration相比,Iterator安全得多,因為它始終拒絕其他線程修改被其迭代的集合對象。
在Java Collections Framework中,迭代器代替了枚舉。 迭代器允許調(diào)用者從基礎(chǔ)集合中刪除Enumeration無法實現(xiàn)的元素。 迭代器方法名稱已得到改進,以使其功能更清晰。
為什么沒有像Iterator.add()這樣的方法將元素添加到集合中?
考慮到Iterator的約定不保證迭代順序,語義尚不清楚。 但是請注意,ListIterator確實提供了添加操作,因為它確實保證了迭代的順序。
為什么Iterator沒有不移動光標就直接獲取下一個元素的方法?
它可以在當前Iterator接口的頂部實現(xiàn),但由于很少使用,因此將其包含在每個人都必須實現(xiàn)的接口中沒有意義。
Iterator和ListIterator有什么區(qū)別?
- 我們可以使用Iterator遍歷Set和List集合,而ListIterator只能與Lists一起使用。
- 迭代器只能向前移動,而ListIterator可以用于兩個方向。
- ListIterator繼承自Iterator接口,并具有其他功能,例如添加元素,替換元素,獲取上一個和下一個元素的索引位置。
有哪些不同的方法可以遍歷列表?
我們可以通過兩種不同的方式遍歷列表-使用迭代器和使用for-each循環(huán)。
List<String> strList = new ArrayList<>();//using for-each loopfor(String obj : strList){System.out.println(obj);}//using iteratorIterator<String> it = strList.iterator();while(it.hasNext()){String obj = it.next();System.out.println(obj);}使用迭代器更加線程安全,因為它可以確保如果基礎(chǔ)列表元素被修改,它將拋出ConcurrentModificationException 。
您對迭代器快速失敗屬性有什么了解?
每當我們嘗試獲取下一個元素時,迭代器fail-fast屬性都會檢查基礎(chǔ)集合的結(jié)構(gòu)是否有任何修改。 如果找到任何修改,則拋出ConcurrentModificationException 。 除了并行并發(fā)類(例如ConcurrentHashMap和CopyOnWriteArrayList)之外,Collection類中Iterator的所有實現(xiàn)在設(shè)計上都是快速失敗的。
快速故障和故障安全之間有何區(qū)別?
Iterator故障安全屬性可與基礎(chǔ)集合的克隆一起使用,因此不受集合中任何修改的影響。 按照設(shè)計, java.util包中的所有收集類都是快速失敗的,而java.util.concurrent中的收集類是故障安全的。 快速故障迭代器會拋出ConcurrentModificationException,而安全故障迭代器絕不會拋出ConcurrentModificationException。 檢查這篇文章中的CopyOnWriteArrayList示例 。
如何在迭代集合時避免ConcurrentModificationException?
我們可以使用并發(fā)集合類來避免在迭代集合時發(fā)生ConcurrentModificationException ,例如,使用CopyOnWriteArrayList而不是ArrayList。
在這篇文章中查看ConcurrentHashMap示例 。
為什么沒有Iterator接口的具體實現(xiàn)?
迭代器接口聲明了用于迭代集合的方法,但是其實現(xiàn)是Collection實現(xiàn)類的責任。 每個返回遍歷迭代器的集合類都有其自己的Iterator實現(xiàn)嵌套類。
這使集合類可以選擇迭代器是快速失敗還是故障安全的。 例如,ArrayList迭代器是快速失敗的,而CopyOnWriteArrayList迭代器是故障安全的。
什么是UnsupportedOperationException?
UnsupportedOperationException是用于指示不支持該操作的異常。 它在JDK類中得到了廣泛使用,在集合框架java.util.Collections.UnmodifiableCollection ,所有add和remove操作都會拋出此異常。
HashMap如何在Java中工作?
HashMap將鍵值對存儲在Map.Entry靜態(tài)嵌套類實現(xiàn)中。 HashMap使用哈希算法,并在put和get方法中使用hashCode()和equals()方法。當我們通過傳遞鍵值對來調(diào)用put方法時,HashMap使用帶有哈希的Key hashCode()來找出存儲密鑰的索引-值對。 該條目存儲在LinkedList中,因此,如果已經(jīng)存在條目,則使用equals()方法檢查傳遞的鍵是否已經(jīng)存在,如果是,它將覆蓋該值,否則它將創(chuàng)建一個新條目并存儲此鍵值條目當我們通過傳遞Key調(diào)用get方法時,它再次使用hashCode()在數(shù)組中查找索引,然后使用equals()方法找到正確的Entry并返回其值。 下圖將清楚地解釋這些細節(jié)。
有關(guān)HashMap的其他重要信息是容量,負載因子,閾值大小調(diào)整。 HashMap的初始默認容量為32,負載系數(shù)為0.75。 閾值是容量乘以負載因子,每當我們嘗試添加條目時,如果映射大小大于閾值,則HashMap會將映射的內(nèi)容重新映射為容量更大的新數(shù)組。 容量始終是2的冪,因此,如果您知道需要存儲大量鍵值對,例如在從數(shù)據(jù)庫緩存數(shù)據(jù)時,最好使用正確的容量和負載因子來初始化HashMap。
hashCode()和equals()方法的重要性是什么?
HashMap使用Key對象的hashCode()和equals()方法來確定放置鍵值對的索引。 當我們嘗試從HashMap中獲取價值時,也會使用這些方法。 如果這些方法的實現(xiàn)不正確,則兩個不同的Key可能會產(chǎn)生相同的hashCode()和equals()輸出,在這種情況下,不是將其存儲在不同的位置,HashMap會將它們視為相同并覆蓋它們。要存儲重復數(shù)據(jù),請使用hashCode()和equals()查找重復數(shù)據(jù),因此正確實現(xiàn)重復數(shù)據(jù)非常重要。 equals()和hashCode()的實現(xiàn)應遵循以下規(guī)則。
- 如果o1.equals(o2) ,則o1.hashCode() == o2.hashCode()應始終為true 。
- 如果o1.hashCode() == o2.hashCode為true,則并不意味著o1.equals(o2)為true 。
- 如果該類重寫equals()方法,則它也應該重寫hashCode()方法。
- 對于所有實例,該類應遵循與equals()和hashCode()關(guān)聯(lián)的規(guī)則。 這些規(guī)則請參考前面的問題。
- 如果equals()中未使用類字段,則不應在hashCode()方法中使用它。
- 用戶定義的鍵類的最佳實踐是使其不可變,以便可以將hashCode()值緩存起來以提高性能。 不可變的類還確保hashCode()和equals()將來不會更改,這將解決任何可變性問題。
例如,假設(shè)我有一個用于MyHashMap鍵的類MyKey 。 //MyKey name argument passed is used for equals() and hashCode() MyKey key = new MyKey('Pankaj'); //assume hashCode=1234 myHashMap.put(key, 'Value');// Below code will change the key hashCode() and equals() // but it's location is not changed. key.setName('Amit'); //assume new hashCode=7890//below will return null, because HashMap will try to look for key //in the same index as it was stored but since key is mutated, //there will be no match and it will return null. myHashMap.get(new MyKey('Pankaj'));這就是為什么String和Integer大多用作HashMap鍵的原因。
Map界面提供哪些不同的Collection視圖?
Map界面提供了三個集合視圖:
- Set keySet():返回此映射中包含的鍵的Set視圖。 該集合由地圖支持,因此對地圖的更改會反映在集合中,反之亦然。 如果在對集合進行迭代時修改了映射(通過迭代器自己的remove操作除外),則迭代的結(jié)果不確定。 該集合支持元素刪除,該元素通過Iterator.remove,Set.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。 它不支持add或addAll操作。
- Collection values():返回此映射中包含的值的Collection視圖。 集合由地圖支持,因此對地圖的更改會反映在集合中,反之亦然。 如果在對集合進行迭代時修改了映射(通過迭代器自己的remove操作除外),則迭代的結(jié)果是不確定的。 集合支持元素刪除,該元素通過Iterator.remove,Collection.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。 它不支持add或addAll操作。
- Set <Map.Entry <K,V >> entrySet() :返回此映射中包含的映射的Set視圖。 該集合由地圖支持,因此對地圖的更改會反映在集合中,反之亦然。 如果在進行集合迭代時修改了映射(除非通過迭代器自己的remove操作或通過迭代器返回的映射條目上的setValue操作),則迭代的結(jié)果是不確定的。 該集合支持元素刪除,該元素通過Iterator.remove,Set.remove,removeAll,retainAll和clear操作從映射中刪除相應的映射。 它不支持add或addAll操作。
HashMap和Hashtable有什么區(qū)別?
HashMap和Hashtable都實現(xiàn)了Map接口,外觀相似,但是HashMap和Hashtable之間存在以下區(qū)別。
- HashMap允許空鍵和值,而Hashtable不允許空鍵和值。
- Hashtable已同步,但HashMap未同步。 因此HashMap更適合單線程環(huán)境,而Hashtable適合多線程環(huán)境。
- LinkedHashMap是Java 1.4中作為HashMap的子類引入的,因此,如果需要迭代順序,則可以輕松地從HashMap切換到LinkedHashMap,但是對于Hashtable而言,情況并非如此,其迭代順序是不可預測的。
- HashMap提供了要迭代的鍵集,因此它是快速失敗的,但是Hashtable提供了不支持此功能的鍵枚舉。
- Hashtable被認為是舊類,如果在迭代時要查找Map的修改,則應使用ConcurrentHashMap。
如何在HashMap和TreeMap之間進行選擇?
為了在Map中插入,刪除和定位元素,HashMap提供了最佳選擇。 但是,如果需要按排序順序遍歷鍵,則TreeMap是更好的選擇。 根據(jù)集合的大小,向HashMap中添加元素,然后將地圖轉(zhuǎn)換為TreeMap以進行排序的鍵遍歷可能更快。
ArrayList和Vector有什么異同?
ArrayList和Vector在許多方面都是相似的類。
- 兩者均基于索引,并由內(nèi)部數(shù)組進行備份。
- 兩者都保持插入順序,我們可以按插入順序獲得元素。
- ArrayList和Vector的迭代器實現(xiàn)在設(shè)計上都是快速失敗的。
- ArrayList和Vector都允許空值和使用索引號隨機訪問元素。
這些是ArrayList和Vector之間的區(qū)別。
- 向量已同步,而ArrayList未同步。 但是,如果要在迭代時查找列表的修改,則應使用CopyOnWriteArrayList。
- ArrayList比Vector更快,因為它沒有任何開銷,因為同步。
- ArrayList更具通用性,因為我們可以使用Collections實用程序類從其中輕松獲取同步列表或只讀列表。
什么時候在ArrayList上使用Array?
數(shù)組可以包含原語或?qū)ο?#xff0c;而ArrayList只能包含對象。
數(shù)組是固定大小的,而ArrayList是動態(tài)的。
數(shù)組沒有提供ArrayList之類的許多功能,例如addAll,removeAll,迭代器等。雖然ArrayList是我們處理列表時的明顯選擇,但很少有數(shù)組可以很好地使用。
- 如果列表的大小是固定的,并且主要用于存儲和遍歷它們。
- 對于原始數(shù)據(jù)類型的列表,盡管Collections使用自動裝箱來減少編碼工作,但是在處理固定大小的原始數(shù)據(jù)類型時,它仍然使它們變慢。
- 如果您正在處理固定的多維情況,則使用[] []遠比List <List <>>更容易
ArrayList和LinkedList有什么區(qū)別?
ArrayList和LinkedList都實現(xiàn)List接口,但是它們之間有一些區(qū)別。
- ArrayList是由Array支持的基于索引的數(shù)據(jù)結(jié)構(gòu),因此它提供對元素的隨機訪問,性能為O(1),但LinkedList將數(shù)據(jù)存儲為節(jié)點列表,每個節(jié)點都鏈接到其上一個和下一個節(jié)點。 因此,即使有一種使用索引獲取元素的方法,在內(nèi)部它也會從開始遍歷到索引節(jié)點,然后返回該元素,因此性能為O(n)比ArrayList慢。
- 與ArrayList相比,LinkedList中元素的插入,添加或刪除要快于ArrayList,因為在中間添加元素時沒有調(diào)整數(shù)組大小或更新索引的概念。
- LinkedList比ArrayList消耗更多的內(nèi)存,因為LinkedList中的每個節(jié)點都存儲上一個和下一個元素的引用。
哪些集合類提供對其元素的隨機訪問?
ArrayList,HashMap,TreeMap,Hashtable類提供對其元素的隨機訪問。 下載java collections pdf了解更多信息。
什么是EnumSet?
java.util.EnumSet是設(shè)置實現(xiàn)以用于枚舉類型。 枚舉集中的所有元素都必須來自創(chuàng)建集時明確或隱式指定的單個枚舉類型。 EnumSet不同步,并且不允許使用null元素。 它還提供了一些有用的方法,例如copyOf(Collection c),of(E first,E…rest)和complementOf(EnumSet s)。請查看此文章以獲取Java枚舉教程 。
哪些集合類是線程安全的?
Vector,Hashtable,Properties和Stack是同步類,因此它們是線程安全的,可以在多線程環(huán)境中使用。 Java 1.5 Concurrent API包含一些集合類,這些類允許在迭代時修改集合,因為它們在集合的克隆上起作用,因此可以在多線程環(huán)境中安全使用。
什么是并發(fā)集合類?
Java 1.5并發(fā)包( java.util.concurrent )包含線程安全的集合類,這些類允許在迭代時修改集合。 通過設(shè)計迭代器是快速失敗的,并拋出ConcurrentModificationException。 這些類中的一些是CopyOnWriteArrayList , ConcurrentHashMap , CopyOnWriteArraySet 。閱讀這些文章以更詳細地了解它們。
- 避免ConcurrentModificationException
- CopyOnWriteArrayList示例
- HashMap與ConcurrentHashMap
什么是BlockingQueue?
java.util.concurrent.BlockingQueue是一個Queue,它支持以下操作:在檢索和刪除元素時等待隊列變?yōu)榉强?#xff0c;在添加元素時等待隊列中的空間變?yōu)榭捎谩lockingQueue接口是其中的一部分java collections框架,它主要用于實現(xiàn)生產(chǎn)者使用者問題。 我們不需要擔心在BlockingQueue中等待生產(chǎn)者或?qū)ο髮οM者可用的空間,因為它由BlockingQueue的實現(xiàn)類處理.Java提供了幾種BlockingQueue實現(xiàn),例如ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue,SynchronousQueue等。
查看此帖子,了解使用BlockingQueue解決生產(chǎn)者-消費者問題 。
什么是隊列和堆棧,列出它們的區(qū)別?
隊列和堆棧都用于存儲數(shù)據(jù),然后再處理它們。 java.util.Queue是一個接口,其實現(xiàn)類存在于Java并發(fā)包中。 隊列允許按照先進先出(FIFO)的順序檢索元素,但情況并非總是如此。 還有一個Deque接口,該接口允許從隊列的兩端檢索元素。
堆棧類似于隊列,不同之處在于堆棧允許按后進先出(LIFO)順序檢索元素。
堆棧是擴展Vector的類,而Queue是接口。
什么是收藏課?
java.util.Collections是一個實用工具類,僅由對集合進行操作或返回集合的靜態(tài)方法組成。 它包含對集合進行操作的多態(tài)算法,“包裝器”,這些包裝器返回由指定集合支持的新集合,以及其他一些零碎的東西。此類包含集合框架算法的方法,例如二進制搜索,排序,改組,反向等
什么是可比和比較器界面?
Java提供了Comparable接口,如果我們想使用Arrays或Collections排序方法,則可以由任何自定義類實現(xiàn)。 可比接口具有compareTo(T obj)方法,該方法由排序方法使用。 如果“此”對象小于,等于或大于作為參數(shù)傳遞的對象,則應以使其返回負整數(shù),零或正整數(shù)的方式重寫此方法。但是,在大多數(shù)現(xiàn)實情況中,我們希望根據(jù)不同的參數(shù)進行排序。 例如,作為首席執(zhí)行官,我想根據(jù)薪水對員工進行分類,而人力資源則想根據(jù)年齡對員工進行分類。 在這種情況下,我們需要使用Comparator接口,因為Comparable.compareTo(Object o)方法實現(xiàn)只能基于一個字段進行排序,而我們無法選擇要對compare(Object o1, Object o2)進行排序的字段.Comparator接口compare(Object o1, Object o2)方法需要采用兩個Object參數(shù),必須以這樣的方式實現(xiàn):如果第一個參數(shù)小于第二個參數(shù),則返回負int;如果相等則返回零;如果第一個參數(shù)等于正數(shù),則返回正int參數(shù)大于第二個參數(shù)。
檢查此帖子以了解使用Comparable和Comparator接口對對象進行排序 。
Comparable和Comparator接口之間有什么區(qū)別?
Comparable和Comparator接口用于對對象的集合或數(shù)組進行排序。Comparable接口用于對對象進行自然排序,我們可以使用它來基于單個邏輯進行排序。
比較器接口用于提供不同的排序算法,我們可以選擇要用于比較給定對象集合的比較器。
我們?nèi)绾闻判驅(qū)ο罅斜?#xff1f;
如果需要對對象數(shù)組進行排序,則可以使用Arrays.sort() 。 如果需要對對象列表進行排序,則可以使用Collections.sort() 。 這兩個類都具有重載的sort()方法,用于自然排序(使用Comparable)或基于條件的排序(使用Comparator)。 集合內(nèi)部使用數(shù)組排序方法,因此兩者的性能相同,只是集合需要一些時間才能將列表轉(zhuǎn)換為數(shù)組。
在將Collection作為參數(shù)傳遞給函數(shù)時,我們?nèi)绾未_保該函數(shù)將無法對其進行修改?
我們可以使用Collections.unmodifiableCollection(Collection c)方法創(chuàng)建一個只讀集合,然后再將其作為參數(shù)傳遞,這將確保任何更改集合的操作都將拋出UnsupportedOperationException 。
我們?nèi)绾螐慕o定的集合中創(chuàng)建一個同步的集合?
我們可以使用Collections.synchronizedCollection(Collection c)來獲取指定集合支持的同步(線程安全)集合。
Collections Framework中實現(xiàn)了哪些常見算法?
Java Collections Framework提供了常用的算法實現(xiàn),例如排序和搜索。 集合類包含這些方法實現(xiàn)。 這些算法大多數(shù)都可以在List上使用,但是其中一些算法適用于所有類型的集合。 其中一些是排序,搜索,混排,最小-最大值。
舉一些例子?
Big-O表示法根據(jù)數(shù)據(jù)結(jié)構(gòu)中元素的數(shù)量來描述算法的性能。 由于Collection類實際上是數(shù)據(jù)結(jié)構(gòu),因此我們通常傾向于使用Big-O表示法根據(jù)時間,內(nèi)存和性能來選擇要使用的collection實現(xiàn)。示例1:ArrayList get(index i)是一個恒定時間的操作,并且不會t取決于列表中元素的數(shù)量。 因此,它在Big-O表示法中的性能為O(1)。
示例2:對數(shù)組或列表性能的線性搜索為O(n),因為我們需要搜索整個元素列表以找到該元素。
與Java Collections Framework相關(guān)的最佳實踐是什么?
- 根據(jù)需要選擇正確的集合類型,例如,如果大小固定,我們可能要在ArrayList上使用Array。 如果必須按插入順序遍歷Map,則需要使用TreeMap。 如果我們不希望重復,則應使用Set。
- 一些收集類允許指定初始容量,因此,如果我們估計要存儲的元素數(shù)量,則可以使用它來避免重新哈希或調(diào)整大小。
- 根據(jù)接口而不是實現(xiàn)來編寫程序,它使我們可以在以后的時間輕松更改實現(xiàn)。
- 始終將泛型用于類型安全,并在運行時避免ClassCastException。
- 使用JDK提供的不可變類作為Map中的鍵,以避免為我們的自定義類實現(xiàn)hashCode()和equals()。
- 盡可能將Collections實用程序類用于算法或獲取只讀,同步或空的Collection,而不是編寫自己的實現(xiàn)。 它將以更高的穩(wěn)定性和較低的可維護性來增強代碼重用。
當我找到它們時,我將繼續(xù)在java集合框架上添加更多問題,如果您發(fā)現(xiàn)它有用,請也與他人分享,這會激發(fā)我編寫更多此類問題的動力。
參考: 40個Java Collections面試問題,來自JCG合作伙伴 Pankaj Kumar,來自Developer Recipes博客。
翻譯自: https://www.javacodegeeks.com/2013/02/40-java-collections-interview-questions-and-answers.html
總結(jié)
以上是生活随笔為你收集整理的40个Java Collections面试问答的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Yammer Metrics,一种监视应
- 下一篇: 电脑屏幕颜色怎么改如何更换电脑屏保