天天看點

java之集合那些事

集合概述:

集合和數組都可以儲存多個對象,但是數組的長度不可變,集合可以儲存數量變化的資料。java中的集合類主要由兩個接口派生出,Collection和Map

Collection接口和Iterator接口:

概述:Collection接口是List,Set和Queue接口的父接口

Collection中的主要方法如下:

方法名稱 方法概述
boolean add(Object o) 該方法向集合中添加一個元素,成功傳回true
boolean addAll(Collection c) 該方法将集合C中的元素添加到指定集合中,成功傳回true
void clear() 清除集合中的元素
boolean contains(Object o) 傳回集合裡是否包含指定元素
boolean containAll(Collection c) 傳回集合中是否包含集合c裡的所有元素
boolean isEmpty() 傳回集合是否為空
Iterator iterator() 傳回一個Iterator對象,用于周遊集合裡的元素
boolean remove(Object o) 删除集合中的指定元素
boolean removeAll(Coolection c) 從指定集合中删除所包含的c集合中的全部元素
boolean retailAll(Coolection c) 從集合中删除集合中不包含的元素
int size() 傳回集合中元素的個數
Object[] toArray() 該方法把集合轉化成一個數組
package cn.itcast.collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

import org.junit.jupiter.api.Test;


public class CollectionTest {
	
	@Test
	public void testCollection(){
		Collection c=new ArrayList();
		c.add("孫悟空");
		c.add(6);
		System.out.println("c集合的元素個數為"+c.size());
		
		c.remove(6);
		System.out.println("c集合的元素個數為"+c.size());
		
		
		System.out.println("c集合中是否包含孫悟空"+c.contains("孫悟空"));
		c.add("javaee實戰");
		System.out.println("c集合中的元素"+c);
		
		Collection books=new HashSet();
		
		books.add("瘋狂java講義");
		books.add("javaee實戰");
		
		System.out.println("c集合是否完全包含books集合"+c.containsAll(books));
		
		c.removeAll(books);
		
		System.out.println("c集合中的元素"+c);
		
		c.clear();
		
		System.out.println("c集合中的元素"+c);
		
		books.retainAll(c);
		
		System.out.println("books集合中的元素:"+books);
		
		
	}
	
	
	
	
	@Test
	public void IteratorTest() {
		Collection<String> c=new ArrayList<String>();
		c.add("java程式設計思想");
		c.add("瘋狂java講義");
		c.add("資料結構與算法");
		Iterator it=c.iterator();
		while(it.hasNext()) {
			String book=(String) it.next();
			System.out.println(book);
			if(book.equals("瘋狂java講義")) {
				it.remove();
			}
			book="測試字元串";
		}
		System.out.println(c);
	}
	

}           

複制

上述代碼主要展示了Collection的常用方法

testCollection方法的執行結果為:

c集合的元素個數為2
c集合的元素個數為1
c集合中是否包含孫悟空true
c集合中的元素[孫悟空, javaee實戰]
c集合是否完全包含books集合false
c集合中的元素[孫悟空]
c集合中的元素[]
books集合中的元素:[]           

複制

IteratorTest方法的執行結果為:

java程式設計思想
瘋狂java講義
資料結構與算法
[java程式設計思想, 資料結構與算法]           

複制

Set集合:

概述:Set集合類似于一個罐子,程式可以依次把多個對象裝進這個罐子裡面,Set集合通常不能記住元素的添加順序。Set集合與Collection集合基本相同。

Set三個常用實作類:

HashSet:

概述:

HashSet是Set接口的典型實作,大多數時候使用Set集合時就是使用這個實作類。 HashSet按Hash算法來存儲集合中的元素,是以具有很好的存取和查找性能。

特點:

1、不能保證元素的排列順序,順序可能與添加順序不同,順序也有可能發生變化

2、HashSet不是同步的,如果多個線程同時通路一個 HashSet,假設有兩個或者兩個以上線程同時修改了 HashSet集合時,則必須通過代碼來保證其同步。

3、集合元素值可以是null

存儲資料原理:

HashSet按Hash算法來存儲集合中的元素,HashSet的内部存儲結構是數組加連結清單。

HashSet存儲元素時首先會根據Hash算法計算出元素在記憶體中的位置,然後将資料存放在相應的位置。如果該位置已經存放有元素,那麼接着調用equals方法判斷這兩個元素是否相等,如果相等則是同一個元素,不需要存儲,如果不相等,說明是不同的元素,此時HashSet會在該位置上産生一個連結清單來存儲這兩個元素,此時HashSet的查找性能會降低。

注意點:

在程式中如果重寫某個類的hashCode()方法,則同時也應該修改其equals方法。  

hashCode方法的重寫規則:

1、在程式運作過程中,同一個對象多次調用 hashCode()方法應該傳回相同的值。

2、當兩個對象通過 equals方法比較傳回tue時,這兩個對象的 hashCode()方法應傳回相等的值

3、對象中用作 equals方法比較标準的執行個體變量,都應該用于計算 hashCode值。

LinkedHashSet:

概述:

LinkedHashSet是HashSet的子類,它的功能和HashSet類似,LinkedHashSet也是根據元素的hashCode值來存儲,但它同時使用連結清單維護元素的資料,這樣使得元素看起來是以插入的順序儲存的。LinkedHashSet需要使用連結清單維護資料,是以性能方面要比HashSet低一點。

TreeSet:

TreeSet是SortedSet接口的實作類,正如SortedSet的名字所示,TreeSet可以確定元素處于排序狀态。與HashSet相比,TreeSet還有其他幾個方法。
方法名稱 方法概述
Comparator comparator() 如果 Tree Set采用了定制排序,則該方法傳回定制排序所使用的Comparator;如果 TreeSet采用了自然排序,則傳回nul
Object first() 傳回集合中的第一個元素
Object last() 傳回集合中的最後一個元素
Object lower(Object e) 傳回集合中位于指定元素之前的元素(即小于指定元素的最大元素,參考元素不需要是集合中的元素)
Object higher(Object e) 傳回集合中位于指定元素之後的元素
SortedSet subSet(Object fromElement,Object toElement) 傳回此Set的子集合,範圍從 fromElement(包含)到 toElement(不包含)。
SortedSet headSet(Object toElement) 傳回此Set的子集,由小于 toLerent的元素組成。
SortedSet tailSet(Object fromElement) 回此Set的子集,由大于或等于 fromElement的元素組成。
package cn.itcast.collection;

import java.util.TreeSet;

public class TreeSetTest {
	
	public static void main(String[] args) {
		
		TreeSet nums=new TreeSet();
		nums.add(5);
		nums.add(2);
		nums.add(10);
		nums.add(-9);
		
		System.out.println(nums);
		
		System.out.println(nums.first());
		System.out.println(nums.last());
		System.out.println(nums.headSet(4));
		System.out.println(nums.tailSet(5));
		System.out.println(nums.subSet(2, 8));
	}

}           

複制

運作結果:

[-9, 2, 5, 10]
-9
10
[-9, 2]
[5, 10]
[2, 5]           

複制

上述代碼展示了TreeSet的常用方法

各個Set集合的性能分析:

1、Hash Set和 TreeSet是Set的兩個典型實作,到底如何選擇 Hash Set和 Tree Set呢? HashSet的性能總是比 TreeSet好(特别是最常用的添加、查詢元素等操作),因為 TreeSet需要額外的紅黑樹算法來維護有Set時,才應該使用 TreeSet,否則都應該使用 HashSet。

2、HashSet還有一個子類:LinkedHash Set,對于普通的插入、删除操作, LinkedHashSet比 HashSet要略微慢一點,這是由維護連結清單所帶來的額外開銷造成的,但由于有了連結清單,周遊 LinkedHashSe會更快。

List集合:

定義:

List集合代表一個元素有序、可重複的集合,集合中每個元素都有其對應的順序索引。List集合允許使用重複元素,可以通過索引來通路指定位置的集合元素。List集合預設按元素的添加順序設定元素的索引,例如第一次添加的元素索引為0,第二次添加的元素索引為1

list集合中特有的方法:

方法名稱 方法描述
void add(int index,Object element) 将元素element插入到集合的指定位置
boolean addAll(int index,Collection c) 将集合c所包含的所有元素插入到List集合的Index處
Object get(int index) 傳回集合index索引處的元素
int indexOf(Object o) 傳回對象o在List集合中第一次出現的位置索引
int lastIndexOf(Object o) 傳回對象o在List集合中最後一次出現的位置索引
Object remove(int index) 删除并傳回Index索引處的位置
Object set(int index,Object element) 将index索引處的元素替換成element對象,傳回被替換的舊元素。

list的基本使用:

List books=new ArrayList();
books.add(new String("輕量級javaee實戰"));
books.add(new String("瘋狂java講義"));
books.add(new String("瘋狂Android講義"));
books.add(new String("瘋狂ios講義"));
		
books.sort((o1,o2)->((String)o1).length()-((String)o2).length());
		
System.out.println(books);
		
books.replaceAll(ele->((String)ele).length());
System.out.println(books);           

複制

list的疊代方法:

String[] books = {"輕量級javaee實戰","瘋狂java講義","瘋狂Android講義","瘋狂ios講義"};
		
List bookList=new ArrayList();
for(int i=0;i<books.length;i++) {
	bookList.add(books[i]);
}

ListIterator lit=bookList.listIterator();
while(lit.hasNext()) {
	System.out.println(lit.next());
	lit.add("------分隔符-----");
}

System.out.println("========下面開始反向疊代======");
while(lit.hasPrevious()) {
	System.out.println(lit.previous());
}           

複制

ArrayList和Vertor:

定義:

ArrayList和Vertor是list的實作類,list中的方法全部都适用于ArrayList和Vertor。ArrayList和Vertor的底層是用數組實作的,ArrayList或 Vector對象使用 initialCapacity參數來設定該數組的長度,當向 ArrayList或 Vector中添加元素超出了該數組的長度時,它們的 initialCapacity會自動增加。

Queue集合:

Queue用于模拟隊列這種資料結構,隊列是先進先出的資料結構。Queue接口中提供了

queue中的方法:

方法名稱 方法描述
void add(Object e) 将元素加入到隊列尾部
Object element() 擷取隊列頭部元素,但是不删除
Boolean offer(Object e) 将元素加入到隊列尾部,當使用容量有限的隊列時,此方法比add效果好
Object peek() 擷取頭部元素,但是不删除
Object poll() 擷取頭部元素,并删除該元素
Object remove() 擷取頭部元素,并删除該元素

LinkedList:

LinkedList也是List的實作類,它與ArrayList不同,LinkedList的底層是基于連結清單實作。同時,LinkedList還實作了Deque接口,可以被當成雙端隊列來使用,是以既可以被當成“棧”來使用,也可以被當成隊列使用

LinkedList的基本使用:

public class LinkedListTest {
	
	public static void main(String[] args) {
		LinkedList books=new LinkedList();
		books.offer("瘋狂java講義");
		books.push("javaee企業級實戰");
		books.offerFirst("瘋狂Android講義");
		for(int i=0;i<books.size();i++) {
			System.out.println("周遊中--"+books.get(i));
		}
		System.out.println(books.peekFirst());
		System.out.println(books.peekLast());
		System.out.println(books.pop());
		System.out.println(books);
		System.out.println(books.pollLast());
		System.out.println(books);
		
	}

}           

複制

List集合的性能分析:

  • ArrayList底層是數組實作的,查詢速度快,增删速度慢,線程不安全
  • Vertor底層是數組實作的,但是Vertor是線程安全的,是以效率較低
  • LinkedList的底層是連結清單實作的,增删速度快,查詢速度慢,線程不安全

如果經常做增删操作,則推薦使用LinkedList,如果經常使用查詢操作,則推薦使用ArrayList,如果兩個操作都多,則推薦使用ArrayList