05-撩課-Java面試寶典-第五篇
阿新 • • 發佈:2018-11-15
41.Iterator、ListIterator 和 Enumeration的區別?
迭代器是一種設計模式, 它是一個物件, 它可以遍歷並選擇序列中的物件, 而開發人員不需要了解 該序列的底層結構。 迭代器通常被稱為“輕量級”物件, 因為建立它的代價小。 Java中的Iterator功能比較簡單, 並且只能單向移動: (1) 使用方法iterator()要求容器返回一個Iterator。 第一次呼叫Iterator的next()方法時, 它返回序列的第一個元素。 注意:iterator()方法是java.lang.Iterable介面 被Collection繼承。 (2) 使用next()獲得序列中的下一個元素。 (3) 使用hasNext()檢查序列中是否還有元素。 (4) 使用remove()將迭代器新返回的元素刪除。 Iterator是Java迭代器最簡單的實現, 為List設計的ListIterator具有更多的功能, 它可以從兩個方向遍歷List, 也可以從List中插入和刪除元素。 ------------- ListIterator的特點: 它的父類介面是Iterator, 名稱是系列表迭代器, 允許程式設計師按任一方向遍歷列表、 迭代期間修改列表, 並獲得迭代器在列表中的當前位置。 ListIterator沒有當前元素, 它的游標位置始終位於呼叫previous() 所返回的元素和呼叫next() 所返回的元素之間。 長度為n的列表的迭代器有n+1個 可能的指標位置。 ------------------ Enumeration的特點: API中是這樣描述的, 它主要是和Vector結合配套使用。 另外此介面的功能與Iterator介面的功能是重複的, 此外,Iterator介面添加了 一個可選的移除操作, 並且使用較短的方法名。 新的實現應該優先 考慮使用Iterator介面 而不是Enumeration介面。 ----------------------- java中的集合類都提供了 返回Iterator的方法, 就是迭代器, 它和Enumeration的主要區別 其實就是Iterator可以刪除元素, 但是Enumration卻不能。
42.Java 中 Set 與 List 有什麼不同?
1、Set 不允許重複,List允許重複 2、Set 沒有順序,List有順序 List介面對Collection進行了簡單的擴充, 它的具體實現類常用的有ArrayList和LinkedList。 你可以將任何東西放到一個List容器中, 並在需要時從中取出。 ArrayList從其命名中可以看出 它是一種類似陣列的形式進行儲存, 因此它的隨機訪問速度極快, 而LinkedList的內部實現是連結串列, 它適合於在連結串列中間 需要頻繁進行插入和刪除操作。 在具體應用時可以根據需要自由選擇。 前面說的Iterator只能對容器進行向前遍歷, 而ListIterator則繼承了Iterator的思想, 並提供了對List進行雙向遍歷的方法。 Set介面也是Collection的一種擴充套件, 而與List不同的時, 在Set中的物件元素不能重複, 也就是說你不能把同樣的東西 兩次放入同一個Set容器中。 它的常用具體實現有HashSet和TreeSet類。 HashSet能快速定位一個元素, 但是你放到HashSet中的物件 需要實現hashCode()方法, 它使用了前面說過的雜湊碼的演算法。 而TreeSet則將放入 其中的元素按序存放, 這就要求你放入 其中的物件是可排序的, 這就用到了集合框架提供的 另外兩個實用類Comparable和Comparator。 一個類是可排序的, 它就應該實現Comparable介面。 有時多個類具有相同的排序演算法, 那就不需要在每分別重複定義 相同的排序演算法, 只要實現Comparator介面即可。 集合框架中還有兩個很實用的公用類: Collections和Arrays。 Collections提供了對一個Collection容器 進行諸如排序、複製、查詢和填充等 一些非常有用的方法, Arrays則是對一個數組進行類似的操作。
43.arraylist 與 vector 的區別?
ArrayList與Vector的區別, 這主要包括兩個方面:. 1.同步性: Vector是執行緒安全的, 也就是說是它的方法之間是執行緒同步的, 而ArrayList是執行緒序不安全的, 它的方法之間是執行緒不同步的。 如果只有一個執行緒會訪問到集合, 那最好是使用ArrayList, 因為它不考慮執行緒安全, 效率會高些; 如果有多個執行緒會訪問到集合, 那最好是使用Vector, 因為不需要我們自己 再去考慮和編寫執行緒安全的程式碼。 備註: 對於Vector&ArrayList、Hashtable&HashMap, 要記住執行緒安全的問題, 記住Vector與Hashtable是舊的, 是java一誕生就提供了的, 它們是執行緒安全的, ArrayList與HashMap是java2時才提供的, 它們是執行緒不安全的。 2.資料增長: ArrayList與Vector 都有一個初始的容量大小, 當儲存進它們裡面的元素的個數超過了容量時, 就需要增加ArrayList與Vector的儲存空間, 每次要增加儲存空間時, 不是隻增加一個儲存單元, 而是增加多個儲存單元, 每次增加的儲存單元的個數 在記憶體空間利用與程式效率之間 要取得一定的平衡。 Vector預設增長為原來兩倍, 而ArrayList的增長策略 在文件中沒有明確規定 從原始碼看到的是增長為原來的1.5倍。 ArrayList與Vector都可以設定初始的空間大小, Vector還可以設定增長的空間大小, 而ArrayList沒有提供 設定增長空間的方法。 總結: 即Vector增長原來的一倍, ArrayList增加原來的0.5倍。
44.什麼類實現了List介面?
List介面的實現類中
最經常使用最重要的就是這三個:
ArrayList、
Vector、
LinkedList。
1.三個都直接實現了AbstractList這個抽象類
2,ArrayList和Vector都實現了
RandomAccess介面。
而LinkedList沒有。
這是什麼意思呢?
在JDK 中,
RandomAccess介面是一個空介面,
所以它沒有實際意義。就是一個標記,
標記這個類支援高速隨機訪問,
所以,arrayList和 vector是支援隨機訪問的,
可是LinkedList不支援持
3.serializbale介面表明他們都支援序列化。
45.什麼類實現了Set介面?
HashSet
LinkedHashSet
TreeSet
HashSet是使用雜湊表(hash table)實現的,
其中的元素是無序的。
HashSet的
add、
remove、
contains方法
的時間複雜度為常量O(1)。
--------------------
TreeSet使用樹形結構
演算法書中的紅黑樹red-black tree
實現的。
TreeSet中的元素是可排序的,
但add、remove和contains方法的時間
複雜度為O(log(n))。
TreeSet還提供了
first()、
last()、
headSet()、
tailSet()等
方法來操作排序後的集合。
-----------------------
LinkedHashSet介於HashSet和TreeSet之間。
它基於一個由連結串列實現的雜湊表,
保留了元素插入順序。
LinkedHashSet中基本方法的
時間複雜度為O(1)。
46.如何保證一個集合執行緒安全?
Java提供了不同層面的執行緒安全支援。
在傳統集合框架內部,
除了Hashtable等同步容器,
還提供了所謂的同步包裝器(Synchronized Wrapper),
可以呼叫Collections工具類提供的包裝方法,
來獲取一個同步的包裝容器,
例如Collections.synchronizedMap()。
但是它們都是利用非常粗粒度的同步方式,
在高併發情況下的效能比較低下。
另外,更加普遍的選擇是利用併發包(java.util.concurrent)
提供的執行緒安全容器類:
各種併發容器,
比如ConcurrentHashMap、
CopyOnWriteArrayList。
各種執行緒安全佇列(Queue/Deque),
比如ArrayBlockingQueue、
SynchronousQueue。
各種有序容器的執行緒安全版本等。
具體保證執行緒安全的方式,
包括有從簡單的synchronized方式,
到基於更加精細化的,
比如基於分離鎖實現的ConcurrentHashMap等併發實現等。
具體選擇要看開發的場景需求,
總體來說,
併發包內提供的容器通用場景,
遠遠優於早期的簡單同步實現。
為什麼需要ConcurrentHashMap
首先,Hashtable本身比較低效,
因為它的實現基本就是
將put、get、size等方法
簡單粗暴地加上“synchronized”。
這就導致了所有併發操作都要競爭同一把鎖,
一個執行緒在進行同步操作時,
其它執行緒只能等待,
大大降低了併發操作的效能。
47.是否可以往 TreeSet 或者 HashSet 中新增 null 元素?
1.TreeSet 是二差樹實現的,
Treeset中的資料是自動排好序的,
不允許放入null值
2.HashSet 是雜湊表實現的,
HashSet中的資料是無序的,
可以放入null,
但只能放入一個null,
兩者中的值都不能重複,
就如資料庫中唯一約束
3.HashSet要求放入的物件
必須實現HashCode()方法,
放入的物件,是以hashcode碼作為標識的,
而具有相同內容的String物件,
hashcode是一樣,
所以放入的內容不能重複。
但是同一個類的物件可以放入不同的例項
48.hashCode() 和 equals() 方法的重要性?如何在Java中使用它們?
Java中的HashMap使用
hashCode()和equals()方法
來確定鍵值對的索引,
當根據鍵獲取值的時候
也會用到這兩個方法。
如果沒有正確的實現這兩個方法,
兩個不同的鍵可能會有相同的hash值,
因此可能會被集合認為是相等的。
而且,這兩個方法也用來發現重複元素,
所以這兩個方法的實現對HashMap的
精確性和正確性是至關重要的。
同一個物件(沒有發生過修改)
無論何時呼叫hashCode(),
得到的返回值必須一樣。
hashCode()返回值相等,
物件不一定相等,
通過hashCode()和equals()
必須能唯一確定一個物件。
一旦重寫了equals(),
就必須重寫hashCode()。
而且hashCode()生成雜湊值的依據應該是
equals()中用來比較是否相等的欄位。
如果兩個由equals()規定相等的物件
生成的hashCode不等,
對於HashMap來說,
他們可能分別對映到不同位置,
沒有呼叫equals()比較是否相等的機會,
兩個實際上相等的物件可能被插入到不同位置,
出現錯誤。
其他一些基於雜湊方法的集合類
可能也會有這個問題。
----------------
怎麼判斷兩個物件是相同的?
使用等號== 判斷兩個物件是否相同,
這種是嚴格的相同,
即記憶體中的同一個物件
Object的equal方法就是使用==判斷兩個物件是否相同
------------
集合set要求元素是唯一的,怎麼實現?
要實現元素的唯一,
需要在往集合set中新增元素時,
判斷集合set是否存在相同的元素,
如果存在,則不新增,反之。
那麼怎麼確定兩個元素是否相同,
1.如果是使用等號==判斷兩個元素是否相同,
即預設使用Object的equals的方法。
2.如果沒有使用等號==判斷兩個元素是否相同,
而是按照某種業務規則判斷兩個元素是否相同,
即重寫了Object的equals的方法。
----------------------
當重寫equals方法,必須重寫hashCode方法嗎?
不是必須的,
得看具體的情況
當equals方法返回的結果和使用等號
比較的結果是一致的時候,
是沒有必要重寫hashCode方法。
當用等號比較物件,
只有是記憶體中同一個物件例項,
才會返回true,
當然呼叫其hashCode()方法
肯定返回相同的值,
這滿足了滿足了hashCode的約束條件,
所以不用重寫hashCode()方法。
當equals方法返回的結果
和使用等號比較的結果是不一致的時候,
就需要重寫hashCode方法。
當重寫後的equals方法
不認為只有是在記憶體中同一個物件例項,
才返回true,
如果不重新hashCode方法()
Object的hashCode()方法 是對記憶體地址的對映,
hashCode方法返回的值肯定是不同的,
這違背了hashCode的約束條件,
所以必須要重新hashCode方法,
並滿足對hashCode的約束條件。
49.array 和 arraylist 的區別?
兩者間的區別:
Array 的容量是固定的,
ArrayList 的容量是根據需求自動擴充套件
ArrayList 提供了 新增、插入或移除
某一範圍元素的方法
而 Array 中,
只能一次獲取或設定一個元素值
用Synchronized方法可以
很容易地建立ArrayList的同步版本
而 Array 將一直保持
它知道使用者實現同步為止
array 陣列的用法
type [] name = new type [size];
注意:size不能省略,type前後要一致
缺點:在資料間插入資料是
ArrayList 動態陣列的用法
是 Array 的複雜版本
動態的增加和減少元素,
實現 ICollection 和 IList 介面
靈活的設定陣列大小
50.如何將一個字串轉換為arraylist?
string 轉 ArrayList
先將字串按照某個字元切割,轉為string陣列
然後用Arrays的asList方法,將陣列轉為List
public class test1 {
public static void main(String[] args) {
//string 轉 ArrayList
String str1 = "a,b,c";
ArrayList<String> list =
new ArrayList<String>(Arrays.asList(str1.split(",")));
System.out.println(list);
}
}
ArrayList 轉 string
public class test1 {
public static void main(String[] args) {
//ArrayList 轉 string
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);//[a, b, c]
String list_str = StringUtils.join(list,",");
System.out.println(list_str);//a,b,c
}
}