一藏研、數(shù)組和集合的比較
數(shù)組不是面向?qū)ο蟮哪叮嬖诿黠@的缺陷咐汞,集合彌補(bǔ)了數(shù)組的缺點(diǎn),比數(shù)組更靈活更實(shí)用儒鹿,而且不同的集合框架類可適用不同場(chǎng)合化撕。如:
1.數(shù)組能存放基本數(shù)據(jù)類型和對(duì)象,而集合類存放的都是對(duì)象的引用约炎,而非對(duì)象本身植阴!
2.數(shù)組容易固定無(wú)法動(dòng)態(tài)改變蟹瘾,集合類容量動(dòng)態(tài)改變。
3.數(shù)組無(wú)法判斷其中實(shí)際存有多少元素掠手,length只告訴了數(shù)組的容量憾朴,而集合的size()可以確切知道元素的個(gè)數(shù)
4.集合有多種實(shí)現(xiàn)方式和不同適用場(chǎng)合,不像數(shù)組僅采用順序表方式
5.集合以類的形式存在喷鸽,具有封裝众雷、繼承、多態(tài)等類的特性魁衙,通過(guò)簡(jiǎn)單的方法和屬性即可實(shí)現(xiàn)各種復(fù)雜操作报腔,大大提高了軟件的開發(fā)效率
二、List集合
有序列表剖淀,允許存放重復(fù)的元素;
實(shí)現(xiàn)類:
ArrayList:數(shù)組實(shí)現(xiàn)纤房,查詢快纵隔,增刪慢,輕量級(jí)炮姨;(線程不安全)
LinkedList:雙向鏈表實(shí)現(xiàn)捌刮,增刪快,查詢慢 (線程不安全)
Vector:數(shù)組實(shí)現(xiàn)舒岸,重量級(jí) (線程安全绅作、使用少)
三、ArrayList
底層是Object數(shù)組蛾派,所以ArrayList具有數(shù)組的查詢速度快的優(yōu)點(diǎn)以及增刪速度慢的缺點(diǎn)俄认。
而在LinkedList的底層是一種雙向循環(huán)鏈表。在此鏈表上每一個(gè)數(shù)據(jù)節(jié)點(diǎn)都由三部分組成:前指針(指向前面的節(jié)點(diǎn)的位置)洪乍,數(shù)據(jù)眯杏,后指針(指向后面的節(jié)點(diǎn)的位置)。最后一個(gè)節(jié)點(diǎn)的后指針指向第一個(gè)節(jié)點(diǎn)的前指針壳澳,形成一個(gè)循環(huán)岂贩。
雙向循環(huán)鏈表的查詢效率低但是增刪效率高。
ArrayList數(shù)組線性表的特點(diǎn)為:類似數(shù)組的形式進(jìn)行存儲(chǔ)巷波,因此它的隨機(jī)訪問速度極快萎津。
ArrayList和LinkedList在用法上沒有區(qū)別,但是在功能上還是有區(qū)別的抹镊。
四锉屈、LinkedList
LinkedList是采用雙向循環(huán)鏈表實(shí)現(xiàn)的。
利用LinkedList實(shí)現(xiàn)棧(stack)髓考、隊(duì)列(queue)部念、雙向隊(duì)列(double-ended queue )。
它具有方法addFirst()、addLast()儡炼、getFirst()妓湘、getLast()、removeFirst()乌询、removeLast()等榜贴。
經(jīng)常用在增刪操作較多而查詢操作很少的情況下:
隊(duì)列和堆棧。
隊(duì)列:先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)妹田。
棧:后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)唬党。
注意:使用棧的時(shí)候一定不能提供方法讓不是最后一個(gè)元素的元素獲得出棧的機(jī)會(huì)。
五鬼佣、集合的遍歷--ArrayList
import java.util.*;
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一種遍歷方法使用foreach遍歷List
for (String str : list) { //也可以改寫for(int i=0;i<list.size();i++)這種形式
System.out.println(str);
}
//第二種遍歷驶拱,把鏈表變?yōu)閿?shù)組相關(guān)的內(nèi)容進(jìn)行遍歷
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //這里也可以改寫為 foreach(String str:strArray)這種形式
{
System.out.println(strArray[i]);
}
//第三種遍歷 使用迭代器進(jìn)行相關(guān)遍歷
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判斷下一個(gè)元素之后有值
{
System.out.println(ite.next());
}
}
}
三種方法都是用來(lái)遍歷ArrayList集合,第三種方法是采用迭代器的方法晶衷,該方法可以不用擔(dān)心在遍歷的過(guò)程中會(huì)超出集合的長(zhǎng)度蓝纲。
六、ArrayList注意點(diǎn)(面試可能會(huì)被問到)
a.如果在初始化ArrayList的時(shí)候沒有指定初始化長(zhǎng)度的話晌纫,默認(rèn)的長(zhǎng)度為10.
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this(10);
}
b.ArrayList在增加新元素的時(shí)候如果超過(guò)了原始的容量的話税迷,ArrayList擴(kuò)容ensureCapacity的方案為“原始容量*3/2+1"哦。
/**
* Increases the capacity of this <tt>ArrayList</tt> instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
c.ArrayList是線程不安全的锹漱,在多線程的情況下不要使用箭养。
如果一定在多線程使用List的,您可以使用Vector哥牍,因?yàn)閂ector和ArrayList基本一致毕泌,區(qū)別在于Vector中的絕大部分方法都
使用了同步關(guān)鍵字修飾,這樣在多線程的情況下不會(huì)出現(xiàn)并發(fā)錯(cuò)誤哦砂心,還有就是它們的擴(kuò)容方案不同懈词,ArrayList是通過(guò)原始
容量*3/2+1,而Vector是允許設(shè)置默認(rèn)的增長(zhǎng)長(zhǎng)度,Vector的默認(rèn)擴(kuò)容方式為原來(lái)的2倍辩诞。
切記Vector是ArrayList的多線程的一個(gè)替代品坎弯。
d.ArrayList實(shí)現(xiàn)遍歷的幾種方法
package com.yonyou.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一種遍歷方法使用foreach遍歷List
for (String str : list) { //也可以改寫for(int i=0;i<list.size();i++)這種形式
System.out.println(str);
}
//第二種遍歷,把鏈表變?yōu)閿?shù)組相關(guān)的內(nèi)容進(jìn)行遍歷
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //這里也可以改寫為foreach(String str:strArray)這種形式
{
System.out.println(strArray[i]);
}
//第三種遍歷 使用迭代器進(jìn)行相關(guān)遍歷
Iterator<String> ite=list.iterator();
while(ite.hasNext())
{
System.out.println(ite.next());
}
}
}
集合數(shù)組的相關(guān)方法
//collection接口方法
Collection<String> t1 = new ArrayList();
//添加元素
t1.add("Jack");
t1.add("Merry");
System.out.println(t1);
//刪除元素
t1.remove("Jack");
System.out.println(t1);
//獲取元素個(gè)數(shù)
System.out.println(t1.size());
//判斷是否包含一個(gè)元素
if (t1.contains("Merry")){
System.out.println("有Merry");
}else {
System.out.println("沒有Merry");
}
//判斷是否為空
if (t1.isEmpty()){
System.out.println("是空的");
}else {
System.out.println("不是空的");
}
//判斷兩個(gè)集合是否相同
Collection<String> t2 = new ArrayList();
t2.add("Merry");
t2.add("Jack");
t2.add("tome");
t2.add("bluck");
if (t1.equals(t2)){
System.out.println("相同");
}else {
System.out.println("不相同");
}
//集合的情空
System.out.println("------------------");
//集合的遍歷
/**1.使用Iterator遍歷
* hasNext 判斷是否有下一個(gè)對(duì)象
* next 獲取下一個(gè)對(duì)象
* remove 刪除當(dāng)前遍歷過(guò)后的對(duì)象
*/
Iterator iterator = t2.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//錯(cuò)誤的方法
while (iterator.next() != null){
System.out.println(iterator.next());
}
System.out.println("------------------");
//2.用for-each 增強(qiáng)for循環(huán)
for (String obj: t2){
System.out.println(obj);
}
//List接口 extends Collection
// ArrayList 內(nèi)部是連續(xù)的內(nèi)存空間 優(yōu)點(diǎn):訪問方便get(); 缺點(diǎn):刪除译暂,添加比較難
// LinkedArrayList 內(nèi)部使用鏈表實(shí)現(xiàn) (不一定連續(xù)) 優(yōu)點(diǎn):增加 刪除效率高 缺點(diǎn):訪問不方便
// 集合里面只能存放對(duì)象
// 包裝類-->Byte Char Integer Long Float Double Boolean
// java會(huì)自動(dòng)將基本數(shù)據(jù)類型包裝為對(duì)應(yīng)的類
ArrayList<Integer> score = new ArrayList<>();
score.add(2);
score.add(3);
score.add(0,1);//在指定位置添加
System.out.println(score);
//訪問元素
score.get(1);
System.out.println(score);
//修改元素 (下標(biāo)抠忘,元素)
score.set(0,0);
System.out.println(score);
//刪除元素 指定下標(biāo)
score.remove(0);
System.out.println(score);
//刪除指定的元素
score.remove((Integer)2);
System.out.println(score);
//清空
score.clear();
System.out.println(score);
ArrayList<Integer> a2 = new ArrayList<>();
a2.add(1);
a2.add(2);
a2.add(3);
a2.add(4);
a2.add(5);
//加入元素 把另一個(gè)集合中的元素加入
score.addAll(a2);
System.out.println(score);
System.out.println("------------------");
ArrayList<Integer> a3 = new ArrayList<>();
a3.add(1);
a3.add(2);
score.retainAll(a3);//取交集
System.out.println(score);
System.out.println("------------------");
ArrayList<Integer> a4 = new ArrayList<>();
a4.add(1);
a4.add(2);
a4.add(3);
a4.add(4);
a4.add(5);
System.out.println(a4.indexOf(1));//第一次出現(xiàn)的位置
System.out.println(a4.lastIndexOf(1));//最后一次出現(xiàn)的位置
System.out.println("------------------");
//將ArrayList轉(zhuǎn)化為普通數(shù)組
Integer[] object = new Integer[a4.size()];
a4.toArray(object);
System.out.println(object);
System.out.println("------------------");
Iterator iterator = a4.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("------------------");
//獲取集合某個(gè)范圍的子集合
List<Integer> integerList = a4.subList(1,3);
System.out.println(integerList);
System.out.println("------------------");
ArrayList<Integer> nums = new ArrayList<>();
nums.add(1);
nums.add(2);
nums.add(3);
nums.add(4);
nums.add(5);
//Lambda表達(dá)式 刪除對(duì)2取余結(jié)果為0的數(shù)
nums.removeIf( obj -> obj % 2 == 0);
System.out.println(nums);
// 1.使用方式:定義一個(gè)類來(lái)實(shí)現(xiàn)接口
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
PXDClass pc = new PXDClass();
ac.test(num, pc);
// 2.使用匿名類
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
ac.test(num, new Show() {
@Override
public void customShow(int element) {
System.out.println(element);
}
});
// 3.使用Lambda表達(dá)式
ArrayClass ac = new ArrayClass();
int[] num = {1,2,3,4,5,6};
ac.test(num, (int element) -> {System.out.println(element);});
}
}
// 閉包 把函數(shù)作為一個(gè)方法的參數(shù)
class ArrayClass{
public void test(int[] target, Show s){
for (int element: target){
s.customShow(element);
}
}
}
// 必須是接口 這個(gè)接口里面只有一個(gè)方法
interface Show{
void customShow(int element);
}
// 實(shí)現(xiàn)Show接口
class PXDClass implements Show{
@Override
public void customShow(int element) {
System.out.println(element);
}
}