真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

java集合類(lèi)代碼詳解 Java常用集合類(lèi)

java集合類(lèi)哪個(gè)函數(shù)可以

java集合里面的函數(shù)

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、重慶小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了蘭州免費(fèi)建站歡迎大家使用!

java集合里面的函數(shù)_java集合【1】——— 從集合接口框架說(shuō)起

百里方欣

原創(chuàng)

關(guān)注

0點(diǎn)贊·155人閱讀

(一) java集合分類(lèi)

之前大概分為三種,Set,List,Map三種,JDK5之后,增加Queue.主要由Collection和Map兩個(gè)接口衍生出來(lái),同時(shí)Collection接口繼承Iterable接口,所以我們也可以說(shuō)java里面的集合類(lèi)主要是由Iterable和Map兩個(gè)接口以及他們的子接口或者其實(shí)現(xiàn)類(lèi)組成。我們可以認(rèn)為Collection接口定義了單列集合的規(guī)范,每次只能存儲(chǔ)一個(gè)元素,而Map接口定義了雙列集合的規(guī)范,每次能存儲(chǔ)一對(duì)元素。

Iterable接口:主要是實(shí)現(xiàn)遍歷功能

Collection接口: 允許重復(fù)

Set接口:無(wú)序,元素不可重復(fù),訪問(wèn)元素只能通過(guò)元素本身來(lái)訪問(wèn)。

List接口:有序且可重復(fù),可以根據(jù)元素的索引來(lái)訪問(wèn)集合中的元素。

Queue接口:隊(duì)列集合

Map接口:映射關(guān)系,簡(jiǎn)單理解為鍵值對(duì),Key不可重復(fù),與Collection接口關(guān)系不大,只是個(gè)別函數(shù)使用到。

整個(gè)接口框架關(guān)系如下(來(lái)自百度百科):

(1) Iterable接口

1. 內(nèi)部定義的方法

java集合最源頭的接口,實(shí)現(xiàn)這個(gè)接口的作用主要是集合對(duì)象可以通過(guò)迭代器去遍歷每一個(gè)元素。

源碼如下:

// 返回一個(gè)內(nèi)部元素為T(mén)類(lèi)型的迭代器(JDK1.5只有這個(gè)接口)

Iterator iterator();

// 遍歷內(nèi)部元素,action意思為動(dòng)作,指可以對(duì)每個(gè)元素進(jìn)行操作(JDK1.8添加)

default void forEach(Consumer super T action) {}

// 創(chuàng)建并返回一個(gè)可分割迭代器(JDK1.8添加),分割的迭代器主要是提供可以并行遍歷元素的迭代器,可以適應(yīng)現(xiàn)在cpu多核的能力,加快速度。

default Spliterator spliterator() {

return Spliterators.spliteratorUnknownSize(iterator(), 0);

}

從上面可以看出,foreach迭代以及可分割迭代,都加了default關(guān)鍵字,這個(gè)是Java 8 新的關(guān)鍵字,以前接口的所有接口,具體子類(lèi)都必須實(shí)現(xiàn),而對(duì)于deafult關(guān)鍵字標(biāo)識(shí)的方法,其子類(lèi)可以不用實(shí)現(xiàn),這也是接口規(guī)范發(fā)生變化的一點(diǎn)。

下面我們分別展示三個(gè)接口的調(diào)用:

1.1 iterator方法

public static void iteratorHasNext(){

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

// 返回迭代器

Iterator iterator=list.iterator();

// hashNext可以判斷是否還有元素

while(iterator.hasNext()){

//next()作用是返回當(dāng)前指針指向的元素,之后將指針移向下個(gè)元素

System.out.println(iterator.next());

}

}

當(dāng)然也可以使用for-each loop方式遍歷

for (String item : list) {

System.out.println(item);

}

但是實(shí)際上,這種寫(xiě)法在class文件中也是會(huì)轉(zhuǎn)成迭代器形式,這只是一個(gè)語(yǔ)法糖。class文件如下:

public class IterableTest {

public IterableTest() { }

public static void main(String[] args) {

iteratorHasNext();

}

public static void iteratorHasNext() {

List list = new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

Iterator iterator = list.iterator();

Iterator var2 = list.iterator();

while(var2.hasNext()) {

String item = (String)var2.next();

System.out.println(item);

}

}

}

需要注意的一點(diǎn)是,迭代遍歷的時(shí)候,如果刪除或者添加元素,都會(huì)拋出修改異常,這是由于快速失敗【fast-fail】機(jī)制。

public static void iteratorHasNext(){

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

for (String item : list) {

if(item.equals("Jam")){

list.remove(item);

}

System.out.println(item);

}

}

從下面的錯(cuò)誤我們可以看出,第一個(gè)元素是有被打印出來(lái)的,也就是remove操作是成功的,只是遍歷到第二個(gè)元素的時(shí)候,迭代器檢查,發(fā)現(xiàn)被改變了,所以拋出了異常。

Jam

Exception in thread "main" java.util.ConcurrentModificationException

at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)

at java.util.ArrayList$Itr.next(ArrayList.java:859)

at IterableTest.iteratorHasNext(IterableTest.java:15)

at IterableTest.main(IterableTest.java:7)

1.2 forEach方法

其實(shí)就是把對(duì)每一個(gè)元素的操作當(dāng)成了一個(gè)對(duì)象傳遞進(jìn)來(lái),對(duì)每一個(gè)元素進(jìn)行處理。

default void forEach(Consumer super T action) {

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

```java

當(dāng)然像ArrayList自然也是有自己的實(shí)現(xiàn)的,那我們就可以使用這樣的寫(xiě)法,簡(jiǎn)潔優(yōu)雅。forEach方法在java8中參數(shù)是`java.util.function.Consumer`,可以稱為**消費(fèi)行為**或者說(shuō)**動(dòng)作**類(lèi)型。

```java

list.forEach(x - System.out.print(x));

同時(shí),我們只要實(shí)現(xiàn)Consumer接口,就可以自定義動(dòng)作,如果不自定義,默認(rèn)迭代順序是按照元素的順序。

public class ConsumerTest {

public static void main(String[] args) {

List list=new ArrayList();

list.add("Jam");

list.add("Jane");

list.add("Sam");

MyConsumer myConsumer = new MyConsumer();

Iterator it = list.iterator();

list.forEach(myConsumer);

}

static class MyConsumer implements Consumer {

@Override

public void accept(Object t) {

System.out.println("自定義打?。? + t);

}

}

}

輸出的結(jié)果:

自定義打?。篔am

自定義打?。篔ane

自定義打?。篠am

1.3 spliterator方法

這是一個(gè)為了并行遍歷數(shù)據(jù)元素而設(shè)計(jì)的迭代方法,返回的是Spliterator,是專門(mén)并行遍歷的迭代器。以發(fā)揮多核時(shí)代的處理器性能,java默認(rèn)在集合框架中提供了一個(gè)默認(rèn)的Spliterator實(shí)現(xiàn),底層也就是Stream.isParallel()實(shí)現(xiàn)的,我們可以看一下源碼:

// stream使用的就是spliterator

default Stream stream() {

return StreamSupport.stream(spliterator(), false);

}

default Spliterator spliterator() {

return Spliterators.spliterator(this, 0);

}

public static Stream stream(Spliterator spliterator, boolean parallel) {

Objects.requireNonNull(spliterator);

return new ReferencePipeline.Head(spliterator,

StreamOpFlag.fromCharacteristics(spliterator),

parallel);

}

使用的方法如下:

public static void spliterator(){

List list = Arrays.asList("1", "2", "3","4","5","6","7","8","9","10");

// 獲取可迭代器

Spliterator spliterator = list.spliterator();

// 一個(gè)一個(gè)遍歷

System.out.println("tryAdvance: ");

spliterator.tryAdvance(item-System.out.print(item+" "));

spliterator.tryAdvance(item-System.out.print(item+" "));

System.out.println("\n-------------------------------------------");

// 依次遍歷剩下的

System.out.println("forEachRemaining: ");

spliterator.forEachRemaining(item-System.out.print(item+" "));

System.out.println("\n------------------------------------------");

// spliterator1:0~10

Spliterator spliterator1 = list.spliterator();

// spliterator1:6~10 spliterator2:0~5

Spliterator spliterator2 = spliterator1.trySplit();

// spliterator1:8~10 spliterator3:6~7

Spliterator spliterator3 = spliterator1.trySplit();

System.out.println("spliterator1: ");

spliterator1.forEachRemaining(item-System.out.print(item+" "));

System.out.println("\n------------------------------------------");

System.out.println("spliterator2: ");

spliterator2.forEachRemaining(item-System.out.print(item+" "));

System.out.println("\n------------------------------------------");

System.out.println("spliterator3: ");

spliterator3.forEachRemaining(item-System.out.print(item+" "));

}

tryAdvance() 一個(gè)一個(gè)元素進(jìn)行遍歷

forEachRemaining() 順序地分塊遍歷

trySplit()進(jìn)行分區(qū)形成另外的 Spliterator,使用在并行操作中,分出來(lái)的是前面一半,就是不斷把前面一部分分出來(lái)

結(jié)果如下:

tryAdvance:

1 2

-------------------------------------------

forEachRemaining:

3 4 5 6 7 8 9 10

------------------------------------------

spliterator1:

8 9 10

------------------------------------------

spliterator2:

1 2 3 4 5

------------------------------------------

spliterator3:

6 7

還有一些其他的用法在這里就不列舉了,主要是trySplit()之后,可以用于多線程遍歷。理想的時(shí)候,可以平均分成兩半,有利于并行計(jì)算,但是不是一定平分的。

2. Collection接口 extend Iterable

Collection接口可以算是集合類(lèi)的一個(gè)根接口之一,一般不能夠直接使用,只是定義了一個(gè)規(guī)范,定義了添加,刪除等管理數(shù)據(jù)的方法。繼承Collection接口的有List,Set,Queue,不過(guò)Queue定義了自己的一些接口,相對(duì)來(lái)說(shuō)和其他的差異比較大。

2.1 內(nèi)部定義的方法

源碼如下:

boolean add(Object o) //添加元素

boolean remove(Object o) //移除元素

boolean addAll(Collection c) //批量添加

boolean removeAll(Collection c) //批量移除

void retainAll(Collection c) // 移除在c中不存在的元素

void clear() //清空集合

int size() //集合大小

boolean isEmpty() //是否為空

boolean contains(Object o) //是否包含在集合中

boolean containsAll(Collection c) //是否包含所有的元素

Iterator iterator() // 獲取迭代器

Object[] toArray() // 轉(zhuǎn)成數(shù)組

default boolean removeIf(Predicate super E filter) {} // 刪除集合中復(fù)合條件的元素,刪除成功返回true

boolean equals(Object o)

int hashCode()

default Spliterator spliterator() {} //獲取可分割迭代器

default Stream stream() {} //獲取流

default Stream parallelStream() {} //獲取并行流

里面獲取并行流的方法parallelStream(),其實(shí)就是通過(guò)默認(rèn)的ForkJoinPool(主要用來(lái)使用分治法(Divide-and-Conquer Algorithm)來(lái)解決問(wèn)題),提高多線程任務(wù)的速度。我們可以使用ArrayList來(lái)演示一下平行處理能力。例如下面的例子,輸出的順序就不一定是1,2,3...,可能是亂序的,這是因?yàn)槿蝿?wù)會(huì)被分成多個(gè)小任務(wù),任務(wù)執(zhí)行是沒(méi)有特定的順序的。

List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

list.parallelStream()

.forEach(out::println);

2.2 繼承Collection的主要接口

graph LR;

Collection --List-有順序,可重復(fù)

List-有順序,可重復(fù) --LinkedList-使用鏈表實(shí)現(xiàn),線程不安全

List-有順序,可重復(fù) --ArrayList-數(shù)組實(shí)現(xiàn),線程不安全

List-有順序,可重復(fù) --Vector-數(shù)組實(shí)現(xiàn),線程安全

Vector-數(shù)組實(shí)現(xiàn),線程安全 --Stack-堆棧,先進(jìn)后出

Collection--Set-不可重復(fù),內(nèi)部排序

Set-不可重復(fù),內(nèi)部排序--HashSet-hash表存儲(chǔ)

HashSet-hash表存儲(chǔ)--LinkHashSet-鏈表維護(hù)插入順序

Set-不可重復(fù),內(nèi)部排序--TreeSet-二叉樹(shù)實(shí)現(xiàn),排序

Collection--Queue-隊(duì)列,先進(jìn)先出

2.2.1 List extend Collection

繼承于Collection接口,有順序,取出的順序與存入的順序一致,有索引,可以根據(jù)索引獲取數(shù)據(jù),允許存儲(chǔ)重復(fù)的元素,可以放入為null的元素。

最常見(jiàn)的三個(gè)實(shí)現(xiàn)類(lèi)就是ArrayList,Vector,LinkedList,ArrayList和Vector都是內(nèi)部封裝了對(duì)數(shù)組的操作,唯一不同的是,Vector是線程安全的,而ArrayList不是,理論上ArrayList操作的效率會(huì)比Vector好一些。

里面是接口定義的方法:

int size(); //獲取大小

boolean isEmpty(); //判斷是否為空

boolean contains(Object o); //是否包含某個(gè)元素

Iterator iterator(); //獲取迭代器

Object[] toArray(); // 轉(zhuǎn)化成為數(shù)組(對(duì)象)

T[] toArray(T[] a); // 轉(zhuǎn)化為數(shù)組(特定位某個(gè)類(lèi))

boolean add(E e); //添加

boolean remove(Object o); //移除元素

boolean containsAll(Collection c); // 是否包含所有的元素

boolean addAll(Collection extends E c); //批量添加

boolean addAll(int index, Collection extends E c); //批量添加,指定開(kāi)始的索引

boolean removeAll(Collection c); //批量移除

boolean retainAll(Collection c); //將c中不包含的元素移除

default void replaceAll(UnaryOperator operator) {}//替換

default void sort(Comparator super E c) {}// 排序

void clear();//清除所有的元素

boolean equals(Object o);//是否相等

int hashCode(); //計(jì)算獲取hash值

E get(int index); //通過(guò)索引獲取元素

E set(int index, E element);//修改元素

void add(int index, E element);//在指定位置插入元素

E remove(int index);//根據(jù)索引移除某個(gè)元素

int indexOf(Object o); //根據(jù)對(duì)象獲取索引

int lastIndexOf(Object o); //獲取對(duì)象元素的最后一個(gè)元素

ListIterator listIterator(); // 獲取List迭代器

ListIterator listIterator(int index); // 根據(jù)索引獲取當(dāng)前的位置的迭代器

List subList(int fromIndex, int toIndex); //截取某一段數(shù)據(jù)

default Spliterator spliterator(){} //獲取可切分迭代器

上面的方法都比較簡(jiǎn)單,值得一提的是里面出現(xiàn)了ListIterator,這是一個(gè)功能更加強(qiáng)大的迭代器,繼承于Iterator,只能用于List類(lèi)型的訪問(wèn),拓展功能例如:通過(guò)調(diào)用listIterator()方法獲得一個(gè)指向List開(kāi)頭的ListIterator,也可以調(diào)用listIterator(n)獲取一個(gè)指定索引為n的元素的ListIterator,這是一個(gè)可以雙向移動(dòng)的迭代器。

操作數(shù)組索引的時(shí)候需要注意,由于List的實(shí)現(xiàn)類(lèi)底層很多都是數(shù)組,所以索引越界會(huì)報(bào)錯(cuò)IndexOutOfBoundsException。

說(shuō)起List的實(shí)現(xiàn)子類(lèi):

ArrayList:底層存儲(chǔ)結(jié)構(gòu)是數(shù)組結(jié)構(gòu),增加刪除比較慢,查找比較快,是最常用的List集合。線程不安全。

LinkedList:底層是鏈表結(jié)構(gòu),增加刪除比較快,但是查找比較慢。線程不安全。

Vector:和ArrayList差不多,但是是線程安全的,即同步。

2.2.2 Set extend Collection

Set接口,不允許放入重復(fù)的元素,也就是如果相同,則只存儲(chǔ)其中一個(gè)。

下面是源碼方法:

int size(); //獲取大小

boolean isEmpty(); //是否為空

boolean contains(Object o); //是否包含某個(gè)元素

Iterator iterator(); //獲取迭代器

Object[] toArray(); //轉(zhuǎn)化成為數(shù)組

T[] toArray(T[] a); //轉(zhuǎn)化為特定類(lèi)的數(shù)組

boolean add(E e); //添加元素

boolean remove(Object o); //移除元素

boolean containsAll(Collection c); //是否包含所有的元素

boolean addAll(Collection extends E c); //批量添加

boolean retainAll(Collection c); //移除所有不存在于c集合中的元素

boolean removeAll(Collection c); //移除所有在c集合中存在的元素

void clear(); //清空集合

boolean equals(Object o); //是否相等

int hashCode(); //計(jì)算hashcode

default Spliterator spliterator() {} //獲取可分割迭代器

主要的子類(lèi):

HashSet

允許空值

通過(guò)HashCode方法計(jì)算獲取hash值,確定存儲(chǔ)位置,無(wú)序。

LinkedHashSet

HashSet的子類(lèi)

有順序

TreeSet

如果無(wú)參數(shù)構(gòu)建Set,則需要實(shí)現(xiàn)Comparable方法。

亦可以創(chuàng)建時(shí)傳入比較方法,用于排序。

2.2.3 Queue extend Collection

隊(duì)列接口,在Collection接口的接觸上添加了增刪改查接口定義,一般默認(rèn)是先進(jìn)先出,即FIFO,除了優(yōu)先隊(duì)列和棧,優(yōu)先隊(duì)列是自己定義了排序的優(yōu)先順序,隊(duì)列中不允許放入null元素。

下面是源碼:

boolean add(E e); //插入一個(gè)元素到隊(duì)列,失敗時(shí)返回IllegalStateException (如果隊(duì)列容量不夠)

boolean offer(E e); //插入一個(gè)元素到隊(duì)列,失敗時(shí)返回false

E remove(); //移除隊(duì)列頭的元素并移除

E poll(); //返回并移除隊(duì)列的頭部元素,隊(duì)列為空時(shí)返回null

E element(); //返回隊(duì)列頭元素

E peek(); //返回隊(duì)列頭部的元素,隊(duì)列為空時(shí)返回null

主要的子接口以及實(shí)現(xiàn)類(lèi)有:

Deque(接口):Queue的子接口,雙向隊(duì)列,可以從兩邊存取

ArrayDeque:Deque的實(shí)現(xiàn)類(lèi),底層用數(shù)組實(shí)現(xiàn),數(shù)據(jù)存貯在數(shù)組中

AbstractQueue:Queue的子接口,僅實(shí)現(xiàn)了add、remove和element三個(gè)方法

PriorityQueue:按照默認(rèn)或者自己定義的順序來(lái)排序元素,底層使用堆(完全二叉樹(shù))實(shí)現(xiàn),使用動(dòng)態(tài)數(shù)組實(shí)現(xiàn),

BlockingQueue: 在java.util.concurrent包中,阻塞隊(duì)列,滿足當(dāng)前無(wú)法處理的操作。

(2) Map接口

定義雙列集合的規(guī)范Map,每次存儲(chǔ)一對(duì)元素,即key和value。

key的類(lèi)型可以和value的類(lèi)型相同,也可以不同,任意的引用類(lèi)型都可以。

key是不允許重復(fù)的,但是value是可以重復(fù)的,所謂重復(fù)是指計(jì)算的hash值系統(tǒng)。

下面的源碼的方法:

V put(K key, V value); // 添加元素

V remove(Object key); // 刪除元素

void putAll(Map extends K, ? extends V m); // 批量添加

void clear() // 移除所有元素

V get(Object key); // 通過(guò)key查詢?cè)?/p>

int size(); // 查詢集合大小

boolean isEmpty(); // 集合是否為空

boolean containsKey(Object key); // 是否包含某個(gè)key

boolean containsValue(Object value); // 是否包含某個(gè)value

Set keySet(); // 獲取所有key的set集合

Collection values(); // 獲取所有的value的set集合

Set entrySet(); // 返回鍵值對(duì)的set,每一個(gè)鍵值對(duì)是一個(gè)entry對(duì)象

boolean equals(Object o); // 用于比較的函數(shù)

int hashCode(); // 計(jì)算hashcode

default V getOrDefault(Object key, V defaultValue) // 獲取key對(duì)應(yīng)的Value,沒(méi)有則返回默認(rèn)值()

default void forEach(BiConsumer super K, ? super V action) {} // 遍歷

default void replaceAll(BiFunction super K, ? super V, ? extends V function) {} // 批量替換

// 缺少這個(gè)key的時(shí)候才會(huì)添加進(jìn)去

// 返回值是是key對(duì)應(yīng)的value值,如果不存在,則返回的是剛剛放進(jìn)去的value

default V putIfAbsent(K key, V value) {}

default boolean remove(Object key, Object value) {} // 移除元素

default boolean replace(K key, V oldValue, V newValue) {} // 替換

default V replace(K key, V value) {} //替換

// 和putIfAbsent有點(diǎn)像,只不過(guò)傳進(jìn)去的mappingFunction是映射函數(shù),也就是如果不存在key對(duì)應(yīng)的value,將會(huì)執(zhí)行函數(shù),函數(shù)返回值會(huì)被當(dāng)成value添加進(jìn)去,同時(shí)返回新的value值

default V computeIfAbsent(K key,Function super K, ? extends V mappingFunction) {}

// 和computeIfAbsent方法相反,只有key存在的時(shí)候,才會(huì)執(zhí)行函數(shù),并且返回

default V computeIfPresent(K key,BiFunction super K, ? super V, ? extends V remappingFunction) {}

// 不管如何都會(huì)執(zhí)行映射函數(shù),返回value

default V compute(K key,BiFunction super K, ? super V, ? extends V remappingFunction) {}

default V merge(K key, V value,BiFunction super V, ? super V, ? extends V remappingFunction) {}

值得注意的是,Map里面定義了一個(gè)Entry類(lèi),其實(shí)就是定義了一個(gè)存儲(chǔ)數(shù)據(jù)的類(lèi)型,一個(gè)entry就是一個(gè).

Map的常用的實(shí)現(xiàn)子類(lèi):

HashMap:由數(shù)組和鏈表組成,線程不安全,無(wú)序。

LinkedHashMap:如果我們需要是有序的,那么就需要它,時(shí)間和空間效率沒(méi)有HashMap那么高,底層是維護(hù)一條雙向鏈表,保證了插入的順序。

ConcurrentHashMap:線程安全,1.7JDK使用鎖分離,每一段Segment都有自己的獨(dú)立鎖,相對(duì)來(lái)說(shuō)效率也比較高。JDK1.8拋棄了Segment,使用Node數(shù)組+鏈表和紅黑樹(shù)實(shí)現(xiàn),在線程安全控制上使用Synchronize和CAS,可以認(rèn)為是優(yōu)化的線程安全的HashMap。

HashTable:對(duì)比與HashMap主要是使用關(guān)鍵字synchronize,加上同步鎖,線程安全。

(二)總結(jié)

這些集合原始接口到底是什么?為什么需要?

我想,這些接口其實(shí)都是一種規(guī)則/規(guī)范的定義,如果不這么做也可以,所有的子類(lèi)自己實(shí)現(xiàn),但是從迭代以及維護(hù)的角度來(lái)說(shuō),這就是一種抽象或者分類(lèi),比如定義了Iterator接口,某一些類(lèi)就可以去繼承或者實(shí)現(xiàn),那就得遵守這個(gè)規(guī)范/契約??梢杂兴卣梗總€(gè)子類(lèi)的拓展不一樣,所以每個(gè)類(lèi)就各有所長(zhǎng),但是都有一個(gè)中心,就是原始的集合接口。比如實(shí)現(xiàn)Map接口的所有類(lèi)的中心思想都不變,只是各有所長(zhǎng),各分千秋,形成了大千集合世界。

【作者簡(jiǎn)介】:

秦懷,公眾號(hào)【秦懷雜貨店】作者,技術(shù)之路不在一時(shí),山高水長(zhǎng),縱使緩慢,馳而不息。個(gè)人寫(xiě)作方向:Java源碼解析,JDBC,Mybatis,Spring,redis,分布式,劍指Offer,LeetCode等,認(rèn)真寫(xiě)好每一篇文章,不喜歡標(biāo)題黨,不喜歡花里胡哨,大多寫(xiě)系列文章,不能保證我寫(xiě)的都完全正確,但是我保證所寫(xiě)的均經(jīng)過(guò)實(shí)踐或者查找資料。遺漏或者錯(cuò)誤之處,還望指正。

平日時(shí)間寶貴,只能使用晚上以及周末時(shí)間學(xué)習(xí)寫(xiě)作,關(guān)注我,我們一起成長(zhǎng)吧~

java集合類(lèi)問(wèn)題

1) System.out.println(list);

2) [Hello,Java,Learn,World]

3)改第一句List list=new LinkedList();

1. ArrayList是實(shí)現(xiàn)了基于動(dòng)態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。

2. 對(duì)于隨機(jī)訪問(wèn)get和set,ArrayList覺(jué)得優(yōu)于LinkedList,因?yàn)長(zhǎng)inkedList要移動(dòng)指針。

3. 對(duì)于新增和刪除操作add和remove,LinedList比較占優(yōu)勢(shì),因?yàn)锳rrayList要移動(dòng)數(shù)據(jù)。

4. ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗相當(dāng)?shù)目臻g。

4)Vector list=new Vector();

1. Vectors是可同步化的,意思就是說(shuō),任何操作Vector的內(nèi)容的方法都是線程安全的,相反的,另一方面,ArrayList是不可同步化的,所以也不是線程安全的。

2. 不管是ArrayList還是Vector,在它們內(nèi)部都是使用一個(gè)數(shù)組來(lái)保存數(shù)據(jù)的。開(kāi)發(fā)過(guò)程中,在使用它們?nèi)魏我粋€(gè)的時(shí)候,你都需要記住這一點(diǎn)。你在往一個(gè)ArrayList或者Vector里插入一個(gè)元素的時(shí)候,如果內(nèi)部數(shù)組空間不夠了,ArrayList或者Vector就要擴(kuò)展它的大小。Vector在默認(rèn)情況下是增長(zhǎng)一倍的大小,而ArrayList增加50%的大小。

楚雄java培訓(xùn)學(xué)校告訴你面試都喜歡問(wèn)的JAVA集合類(lèi)?

了一些所謂大公司的Java面試問(wèn)題,發(fā)現(xiàn)對(duì)于JAVA集合類(lèi)的使用都比較看重似的,而自己在這方面還真的是所真甚少,抽空也學(xué)習(xí)學(xué)習(xí)吧。

java.util包中就包含了一系列重要的集合類(lèi),而對(duì)于集合類(lèi),主要需要掌握的就是它的內(nèi)部結(jié)構(gòu),以及遍歷集合的迭代模式。

接口:Collection

所有集合類(lèi)的根類(lèi)型,主要的一個(gè)接口方法:booleanadd(Ojbectc)

雖返回的是boolean,但不是表示添加成功與否,因?yàn)镃ollection規(guī)定:一個(gè)集合拒絕添加這個(gè)元素,無(wú)論什么原因,都必須拋出異常,這個(gè)返回值表示的意義是add()執(zhí)行后,集合的內(nèi)容是否改了(就是元素有無(wú)數(shù)量、位置等變化)。類(lèi)似的addAll,remove,removeAll,remainAll也是一樣的。

用Iterator模式實(shí)現(xiàn)遍歷集合

Collection有一個(gè)重要的方法:iterator(),返回一個(gè)Iterator(迭代子),用于遍歷集合的所有元素。Iterator模式可以把訪問(wèn)邏輯從不同類(lèi)的集合類(lèi)中抽象出來(lái),從而避免向客戶端暴露集合的內(nèi)部結(jié)構(gòu)。

for(Iteratorit=c.iterator();it.hasNext();){...}

不需要維護(hù)遍歷集合的“指針”,所有的內(nèi)部狀態(tài)都有Iterator來(lái)維護(hù),而這個(gè)Iterator由集合類(lèi)通過(guò)工廠方法生成。

每一種集合類(lèi)返回的Iterator具體類(lèi)型可能不同,但它們都實(shí)現(xiàn)了Iterator接口,因此,我們不需要關(guān)心到底是哪種Iterator,它只需要獲得這個(gè)Iterator接口即可,這就是接口的好處,面向?qū)ο蟮耐Α?/p>

要確保遍歷過(guò)程順利完成,電腦培訓(xùn)認(rèn)為必須保證遍歷過(guò)程中不更改集合的內(nèi)容(Iterator的remove()方法除外),所以,確保遍歷可靠的原則是:只在一個(gè)線程中使用這個(gè)集合,或者在多線程中對(duì)遍歷代碼進(jìn)行同步。

JAVA里面set,map,list的區(qū)別是什么?(盡量詳細(xì))

java集合的主要分為三種類(lèi)型:

Set(集)

List(列表)

Map(映射)

要深入理解集合首先要了解下我們熟悉的數(shù)組:

數(shù)組是大小固定的,并且同一個(gè)數(shù)組只能存放類(lèi)型一樣的數(shù)據(jù)(基本類(lèi)型/引用類(lèi)型),而JAVA集合可以存儲(chǔ)和操作數(shù)目不固定的一組數(shù)據(jù)。 所有的JAVA集合都位于 java.util包中! JAVA集合只能存放引用類(lèi)型的的數(shù)據(jù),不能存放基本數(shù)據(jù)類(lèi)型。

簡(jiǎn)單說(shuō)下集合和數(shù)組的區(qū)別:(參考文章:《Thinking In Algorithm》03.數(shù)據(jù)結(jié)構(gòu)之?dāng)?shù)組)

Java所有“存儲(chǔ)及隨機(jī)訪問(wèn)一連串對(duì)象”的做法,array是最有效率的一種。

1、

效率高,但容量固定且無(wú)法動(dòng)態(tài)改變。

array還有一個(gè)缺點(diǎn)是,無(wú)法判斷其中實(shí)際存有多少元素,length只是告訴我們array的容量。

2、Java中有一個(gè)Arrays類(lèi),專門(mén)用來(lái)操作array。

arrays中擁有一組static函數(shù),

equals():比較兩個(gè)array是否相等。array擁有相同元素個(gè)數(shù),且所有對(duì)應(yīng)元素兩兩相等。

fill():將值填入array中。

sort():用來(lái)對(duì)array進(jìn)行排序。

binarySearch():在排好序的array中尋找元素。

System.arraycopy():array的復(fù)制。

若撰寫(xiě)程序時(shí)不知道究竟需要多少對(duì)象,需要在空間不足時(shí)自動(dòng)擴(kuò)增容量,則需要使用容器類(lèi)庫(kù),array不適用。所以就要用到集合。

那我們開(kāi)始討論java中的集合。

集合分類(lèi):

Collection:List、Set

Map:HashMap、HashTable

java集合是什么?

Java集合是什么:

Java 中的集合類(lèi)庫(kù)可以幫助我們?cè)诔绦蛟O(shè)計(jì)中實(shí)現(xiàn)傳統(tǒng)的數(shù)據(jù)結(jié)構(gòu)。

Java的集合類(lèi)是一個(gè)用來(lái)存放對(duì)象的容器,有以下特點(diǎn):

1、Java集合只能存放對(duì)象。加入添加了一個(gè)基本數(shù)據(jù)類(lèi)型,會(huì)被自動(dòng)裝箱后存入集合。

2、集合存放的是多個(gè)對(duì)象的引用,對(duì)象本身是在堆內(nèi)存中的。

3、集合可以存放不同類(lèi)型,不限數(shù)量的數(shù)據(jù)類(lèi)型。

集合分三種:1、Set 2 、List 3、Map,下面進(jìn)行具體介紹。

擴(kuò)展鏈接:

主要內(nèi)容:

1)手寫(xiě)ArrayList

2)手寫(xiě)單鏈表

3)手寫(xiě)LinkedList

4)手寫(xiě)HashMap

5)手寫(xiě)HashSet

6)最新并發(fā)集合類(lèi)

學(xué)習(xí)目標(biāo):

1. 掌握手寫(xiě)ArrayList

2. 掌握手寫(xiě)單鏈表

3. 掌握手寫(xiě)LinkedList

4. 掌握手寫(xiě)HashMap

5. 掌握手寫(xiě)HashSet

6. 理解最新并發(fā)集合類(lèi)底層原理

視頻課程小結(jié):

01_集合提升訓(xùn)練_手寫(xiě)ArrayList_get_size_isEmpty_自定義異常

02_集合提升訓(xùn)練_手寫(xiě)ArrayList_構(gòu)造方法_add

03_集合提升訓(xùn)練_手寫(xiě)ArrayList_toString_iterator

04_集合提升循環(huán)_手寫(xiě)單鏈表_get

05_集合提升訓(xùn)練_手寫(xiě)單鏈表_add_remove_toString

06_集合提升訓(xùn)練_手寫(xiě)LinkedList

07_集合提升訓(xùn)練_手寫(xiě)LinkedList_添加內(nèi)存分配圖

08_集合提升訓(xùn)練_HashMap的原理和代碼準(zhǔn)備

09_集合提升訓(xùn)練_手寫(xiě)HashMap的put

10_集合提升訓(xùn)練_手寫(xiě)HashMap的get_toString

11_集合提升訓(xùn)練_手寫(xiě)HashSet

12_集合提升訓(xùn)練_新一代并發(fā)集合類(lèi)

Java中集合類(lèi)的區(qū)別,請(qǐng)高手詳解

ArrayList 實(shí)現(xiàn)List接口 ,隨著向 ArrayList 中不斷添加元素,其容量也自動(dòng)增長(zhǎng)

Vector向量 不過(guò)我是不太喜歡這個(gè)類(lèi)

HashMap實(shí)現(xiàn)Map接口--可以說(shuō)內(nèi)存就是一個(gè)HashMap

HashTable實(shí)現(xiàn)一個(gè)哈希表,該哈希表將鍵映射到相應(yīng)的值

Set一個(gè)不包含重復(fù)元素的容器

HashMap, HashTable都是“Key-Value對(duì)”形式的

Vector和ArrayList區(qū)別

Vector和ArrayList Vector和ArrayList在使用上非常相似,都可用來(lái)表示一組數(shù)量可變的對(duì)象應(yīng)用的集合,并且可以隨機(jī)地訪問(wèn)其中的元素。

Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由于線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。

當(dāng)Vector或ArrayList中的元素超過(guò)它的初始大小時(shí),Vector會(huì)將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利于節(jié)約內(nèi)存空間。

Hashtable和HashMap的區(qū)別

Hashtable和HashMap它們的性能方面的比較類(lèi)似 Vector和ArrayList,比如Hashtable的方法是同步的,而HashMap的不是。

ArrayList和LinkedList的區(qū)別

對(duì)于處理一列數(shù)據(jù)項(xiàng),Java提供了兩個(gè)類(lèi)ArrayList和LinkedList, ArrayList的內(nèi)部實(shí)現(xiàn)是基于內(nèi)部數(shù)組Object[], 所以從概念上講,它更象數(shù)組,但LinkedList的內(nèi)部實(shí)現(xiàn)是基于一組連接的記錄,所以,它更象一個(gè)鏈表結(jié)構(gòu),所以,它們?cè)谛阅苌嫌泻艽蟮牟顒e。

從上面的分析可知,在ArrayList的前面或中間插入數(shù)據(jù)時(shí),你必須將其后的所有數(shù)據(jù)相應(yīng)的后移,這樣必然要花費(fèi)較多時(shí)間,所以,當(dāng)你的操作是在一列 數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問(wèn)其中的元素時(shí),使用ArrayList會(huì)提供比較好的性能

而訪問(wèn)鏈表中的某個(gè)元素時(shí),就必須從鏈表的一端開(kāi)始沿著連接方向一個(gè)一個(gè)元素地去查找,直到找到所需的元素為止,所以,當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問(wèn)其中的元素時(shí),就應(yīng)該使用LinkedList了。

如果在編程中,1,2兩種情形交替出現(xiàn),這時(shí),你可以考慮使用List這樣的通用接口,而不用關(guān)心具體的實(shí)現(xiàn),在具體的情形下,它的性能由具體的實(shí)現(xiàn)來(lái)保證。

配置集合類(lèi)的初始大小

在Java集合框架中的大部分類(lèi)的大小是可以隨著元素個(gè)數(shù)的增加而相應(yīng)的增加的,我們似乎不用關(guān)心它的初始大小,但如果我們考慮類(lèi)的性能問(wèn)題時(shí),就一定要考慮盡可能地設(shè)置好集合對(duì)象的初始大小,這將大大提高代碼的性能。

比如,Hashtable缺省的初始大小為101,載入因子為0.75,即如果其中的元素個(gè)數(shù)超過(guò)75個(gè),它就必須增加大小并重新組織元素,所以,如果你 知道在創(chuàng)建一個(gè)新的Hashtable對(duì)象時(shí)就知道元素的確切數(shù)目如為110,那么,就應(yīng)將其初始大小設(shè)為110/0.75=148,這樣,就可以避免重 新組織內(nèi)存并增加大小。


名稱欄目:java集合類(lèi)代碼詳解 Java常用集合類(lèi)
網(wǎng)站路徑:http://weahome.cn/article/hjcopj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部