2020/3/30學習筆記-day29【java高級特性(二)】

java-day29

java高級特性-第二部分

1、集合(Collection Framework)

Java中集合和相關的接口都在java.util包下。

集合的主要組成部分

1-1接口

整個集合架構的上層結構都是用接口進行組織的,接口中定義了將來集合中必須要有的基本方法。

通過接口還把集合劃分成了幾種不同的類型,每一種集合都有其對應的接口。

1-2實現類

對於上層接口劃分好的集合類型,都會有對應的類型進行實現。每一種接口的實現類很可能有多個,每個的實現方法也會各有不同。

1-3實現的方法(算法)

每個實現類都實現了接口中所定義的最基本的方法,對數據的存儲、檢索、操作等這些方法,但是不同的實現類,他們的實現方法不同,也就是算法不同。

2、集合和數組的區別

集合對象是用來存放其他對象的,並且只能存放對象,不能存放基本數據類型。

數組對象可以存放對象也可以存放基本數據類型。

因爲數組可以聲明爲引用類型和基本類型數組。

集合的長度是可以變化的,隨着存儲數據的增多,集合中的總長度也會隨之變化。

數組的長度一旦確定,就無法改變。

集合是由javase-api中的java-util包裏面所提供的接口和實現類組成的,這裏面定義並實現了很多方法,我們可以使用集合對象直接調用,然後完成對集合中數據的操作。

數組是JVM中實現的,類型+[ ] 組合而成,除了一個length屬性,還有從Object中繼承過來的方法外,我們用數組對象就調用不到其他屬性和方法。

3、集合框架的組成

集合中分爲兩個大的類型:Collection 和 Map

Iterable 接口

Collection 接口

Collection父接口

Iterable <E> 

Collection子接口

BeanContext
BeanContextServices
BlockingDeque <E>
BlockingQueue <E>
Deque <E>
List <E> 
NavigableSet <E> 
Queue <E>
Set <E>
SortedSet <E>
TransferQueue <E> 

Collection實現類

AbstractCollection , AbstractList ,
AbstractQueue , AbstractSequentialList ,
AbstractSet , ArrayBlockingQueue , ArrayDeque , 
【ArrayList】 , AttributeList , 
BeanContextServicesSupport , 
BeanContextSupport , 
ConcurrentHashMap.KeySetView , 
ConcurrentLinkedDeque , ConcurrentLinkedQueue , 
ConcurrentSkipListSet ,
CopyOnWriteArrayList ,
CopyOnWriteArraySet ,
DelayQueue , EnumSet , 
【HashSet】 , JobStateReasons ,
LinkedBlockingDeque ,
LinkedBlockingQueue ,
LinkedHashSet , 【LinkedList】 ,
LinkedTransferQueue , 
PriorityBlockingQueue ,
PriorityQueue , RoleList ,
RoleUnresolvedList , Stack , 
SynchronousQueue , 【TreeSet】 ,【Vector】 

在這裏插入圖片描述

注意:SortedMap是Map接口下面的子接口

4、每一種集合類型的特點

Iterable接口

這個接口不代表集合,但是很多集合實現了這個接口,集合實現這個接口後,就可以實現迭代功能。

Iterable接口中的抽象方法:

Iterator<T> iterator() 
返回類型爲 T元素的迭代器

實現這個接口的集合中,都可以調用iterator()方法,該方法返回一個迭代器,使用這個迭代器就要可以迭代出集合的每一個元素。

該方法的返回類型是Iterator,這也是一個接口表示迭代器類型。

Collection接口

這個接口代表一種結合類型。這個接口繼承了父接口Iterable,所以只要實現這個接口的集合都可以調用iterator() 方法來獲取迭代器,從而迭代集合中的元素。

所有方法

boolean 	add(E e) 
			確保此集合包含指定的元素(可選操作)。  

boolean 	addAll(Collection<? extends E> c) 
			將指定集合中的所有元素添加到此集合(可選操作)。  

void 		clear() 
			從此集合中刪除所有元素(可選操作)。  

boolean 	contains(Object o) 
			如果此集合包含指定的元素,則返回 true 。  

boolean 	containsAll(Collection<?> c) 
			如果此集合包含指定 集合中的所有元素,則返回true。  

boolean 	equals(Object o) 
			將指定的對象與此集合進行比較以獲得相等性。  

int 		hashCode() 
			返回此集合的哈希碼值。  

boolean 	isEmpty() 
			如果此集合不包含元素,則返回 true 。  

Iterator<E> iterator() 
			返回此集合中的元素的迭代器。  

boolean 	remove(Object o) 
			從該集合中刪除指定元素的單個實例(如果存在)(可選操作)。  

boolean 	removeAll(Collection<?> c) 
			刪除指定集合中包含的所有此集合的元素(可選操作)。  

boolean 	retainAll(Collection<?> c) 
			僅保留此集合中包含在指定集合中的元素(可選操作)。  

int 		size() 
			返回此集合中的元素數。  

Object[] 	toArray() 
			返回一個包含此集合中所有元素的數組。  

<T> T[] 	toArray(T[] a) 
			返回包含此集合中所有元素的數組;
			返回的數組的運行時類型是指定數組的運行時類型。
			
---------------默認方法------------------
					
default boolean 		removeIf(Predicate<? super E> filter) 
						刪除滿足給定謂詞的此集合的所有元素
					
default Stream<E> 		parallelStream() 
						返回可能並行的 Stream與此集合作爲其來源。  
                        
default Spliterator<E> 	spliterator() 
						創建一個Spliterator在這個集合中的元素。  

default Stream<E> 		stream() 
						返回以此集合作爲源的順序 Stream 。

List接口和Set接口

這兩個接口都是Collection接口的子接口。

List接口的特點:

有序可重複

往List集合中所存儲的數據是有序的(該順序是存放的順序)

可以將同一個數據重複存到List集合中

List新增加的方法:
boolean 	addAll(int index, Collection<? extends E> c) 
			將指定集合中的所有元素插入到此列表中的指定位置(可選操作)。
			
E 			get(int index) 
			返回此列表中指定位置的元素。
            
E 			remove(int index) 
			刪除該列表中指定位置的元素(可選操作)。
            
E 			set(int index, E element) 
			用指定的元素(可選操作)替換此列表中指定位置的元素
			
int 		indexOf(Object o) 
			返回此列表中指定元素的第一次出現的索引,如果此列表不包含元素,則返回-1。            

void 		add(int index, E element) 
			將指定的元素插入此列表中的指定位置(可選操作)。
            
int 		lastIndexOf(Object o) 
			返回此列表中指定元素的最後一次出現的索引,如果此列表不包含元素,則返回-1。
            
List<E> 	subList(int fromIndex, int toIndex) 
			返回此列表中指定的 fromIndex (含)和 toIndex之間的視圖。  

ListIterator<E> 	listIterator() 
					返回列表中的列表迭代器(按適當的順序)。 
                    
ListIterator<E> 	listIterator(int index) 
					從列表中的指定位置開始,返回列表中的元素(按正確順序)的列表迭代器。  
Set接口的特點:

無序不可重複

往Set類型集合中存儲的順序默認是無序的

Set類型集合不能存放相同的數據(HashCode 和 equals來進行判斷)

注意:Set接口的一個子接口SortedSet,是允許把存放到集合中的數據進行排序的。

Set新增加的方法:
default Spliterator<E> 	spliterator() 
						在此集合中的元素上創建一個 Spliterator 。  

Map接口

Map是和Collection不同的一種集合。

Map中存放數據的特點和Collection不同,Collection就是直接把數據存放進去就可以了,但是Map要求存放進去的數據都要有一個唯一的標識。

Map存放的數據都要以K-V的方式進行存放,V:存放的數據,K:這個數據在Map中的唯一標識,鍵值對(Key-Value)。

void 	clear() 
		從該Map中刪除所有的映射(可選操作)。  
		
boolean containsKey(Object key) 
		如果此映射包含指定鍵的映射,則返回 true 。  
		
boolean containsValue(Object value) 
		如果此Map將一個或多個鍵映射到指定的值,則返回 true 。  
  
boolean equals(Object o) 
		將指定的對象與此映射進行比較以獲得相等性。 
		
V 		get(Object key) 
		返回到指定鍵所映射的值,或 null如果此映射包含該鍵的映射。
		
int 	size() 
		返回此Map中鍵值映射的數量。  
		
int 	hashCode() 
		返回此Map的哈希碼值。  
		
boolean isEmpty() 
		如果此Map不包含鍵值映射,則返回 true 。 
        
Set<K>	keySet() 
		返回此Map中包含的鍵的Set視圖。
		
V 		put(K key, V value) 
		將指定的值與該映射中的指定鍵相關聯(可選操作)。
		
Collection<V> 		values() 
					返回此Map中包含的值的Collection視圖。
					
Set<Map.Entry<K,V>> entrySet() 
					返回此Map中包含的映射的Set視圖。
					
void 				putAll(Map<? extends K,? extends V> m) 
					將指定Map的所有映射覆制到此映射(可選操作)。
					
V 					remove(Object key) 
					如果存在(從可選的操作),從該Map中刪除一個鍵的映射。  
...(default方法未放出來) 

5、集合中的實現類

List接口的實現類中常用的有ArrayList、LinkedList、Vector

ArrayList實現類的聲明:(用數組實現)

public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable{
    //....
}
boolean 	add(E e) 
			將指定的元素追加到此列表的末尾。  
void 		add(int index, E element) 
			在此列表中的指定位置插入指定的元素。  
boolean 	addAll(Collection<? extends E> c) 
			按指定集合的Iterator返回的順序將指定集合中的所有元素追加到此列表的末尾。  
boolean 	addAll(int index, Collection<? extends E> c) 
			將指定集合中的所有元素插入到此列表中,從指定的位置開始。  
void 		clear() 
			從列表中刪除所有元素。  
Object 		clone() 
			返回此 ArrayList實例的淺拷貝。  
boolean 	contains(Object o) 
			如果此列表包含指定的元素,則返回 truevoid 		ensureCapacity(int minCapacity) 
			如果需要,增加此 ArrayList實例的容量,以確保它可以至少保存最小容量參數指定的元素數。  
void 		forEach(Consumer<? super E> action) 
			對 Iterable的每個元素執行給定的操作,直到所有元素都被處理或動作引發異常。  
E 			get(int index) 
			返回此列表中指定位置的元素。  
int 		indexOf(Object o) 
			返回此列表中指定元素的第一次出現的索引,如果此列表不包含元素,則返回-1boolean 	isEmpty() 
			如果此列表不包含元素,則返回 true 。  
Iterator<E> iterator() 
			以正確的順序返回該列表中的元素的迭代器。  
int 		lastIndexOf(Object o) 
			返回此列表中指定元素的最後一次出現的索引,如果此列表不包含元素,則返回-1。  
E 			remove(int index) 
			刪除該列表中指定位置的元素。  
boolean 	remove(Object o) 
			從列表中刪除指定元素的第一個出現(如果存在)。  
boolean 	removeAll(Collection<?> c) 
			從此列表中刪除指定集合中包含的所有元素。  
boolean 	removeIf(Predicate<? super E> filter) 
			刪除滿足給定謂詞的此集合的所有元素。  
void 		replaceAll(UnaryOperator<E> operator) 
			將該列表的每個元素替換爲將該運算符應用於該元素的結果。  
boolean 	retainAll(Collection<?> c) 
			僅保留此列表中包含在指定集合中的元素。  
E 			set(int index, E element) 
			用指定的元素替換此列表中指定位置的元素。  
int 		size() 
			返回此列表中的元素數。  
void 		sort(Comparator<? super E> c) 
			使用提供的 Comparator對此列表進行排序以比較元素。   
List<E> 	subList(int fromIndex, int toIndex) 
			返回此列表中指定的 fromIndex (包括)和 toIndex之間的獨佔視圖。  
Object[] 	toArray() 
			以正確的順序(從第一個到最後一個元素)返回一個包含此列表中所有元素的數組。  
<T> T[] 	toArray(T[] a) 
			以正確的順序返回一個包含此列表中所有元素的數組(從第一個到最後一個元素); 
			返回的數組的運行時類型是指定數組的運行時類型。  
void 		trimToSize() 
			修改這個 ArrayList實例的容量是列表的當前大小。  			
Spliterator<E> 	spliterator() 
				在此列表中的元素上創建late-binding和故障快速 Spliterator 。			
protected void 	removeRange(int fromIndex, int toIndex) 
				從這個列表中刪除所有索引在 fromIndex (含)和 toIndex之間的元素。  
ListIterator<E> listIterator() 
				返回列表中的列表迭代器(按適當的順序)。  
ListIterator<E> listIterator(int index) 
				從列表中的指定位置開始,返回列表中的元素(按正確順序)的列表迭代器。  

LinkedList實現類的聲明:(用鏈表實現)

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
   		 //...
    }
boolean 	add(E e) 
			將指定的元素追加到此列表的末尾。  
void 		add(int index, E element) 
			在此列表中的指定位置插入指定的元素。  
boolean 	addAll(Collection<? extends E> c) 
			按照指定集合的迭代器返回的順序將指定集合中的所有元素追加到此列表的末尾。  
boolean 	addAll(int index, Collection<? extends E> c) 
			將指定集合中的所有元素插入到此列表中,從指定的位置開始。  
void 		addFirst(E e) 
			在該列表開頭插入指定的元素。  
void 		addLast(E e) 
			將指定的元素追加到此列表的末尾。  
void 		clear() 
			從列表中刪除所有元素。  
Object 		clone() 
			返回此 LinkedList的淺版本。  
boolean 	contains(Object o) 
			如果此列表包含指定的元素,則返回 true 。  
Iterator<E> descendingIterator() 
			以相反的順序返回此deque中的元素的迭代器。  
E 			element() 
			檢索但不刪除此列表的頭(第一個元素)。  
E 			get(int index) 
			返回此列表中指定位置的元素。  
E 			getFirst() 
			返回此列表中的第一個元素。  
E 			getLast() 
			返回此列表中的最後一個元素。  
int 		indexOf(Object o) 
			返回此列表中指定元素的第一次出現的索引,如果此列表不包含元素,則返回-1int 		lastIndexOf(Object o) 
			返回此列表中指定元素的最後一次出現的索引,如果此列表不包含元素,則返回-1。  
ListIterator<E> listIterator(int index) 
				從列表中的指定位置開始,返回此列表中元素的列表迭代器(按適當的順序)。  
boolean 	offer(E e) 
			將指定的元素添加爲此列表的尾部(最後一個元素)。  
boolean 	offerFirst(E e) 
			在此列表的前面插入指定的元素。  
boolean		offerLast(E e) 
			在該列表的末尾插入指定的元素。  
E 			peek() 
			檢索但不刪除此列表的頭(第一個元素)。  
E 			peekFirst() 
			檢索但不刪除此列表的第一個元素,如果此列表爲空,則返回 null 。  
E 			peekLast() 
			檢索但不刪除此列表的最後一個元素,如果此列表爲空,則返回 null 。  
E 			poll() 
			檢索並刪除此列表的頭(第一個元素)。  
E 			pollFirst() 
			檢索並刪除此列表的第一個元素,如果此列表爲空,則返回 null 。  
E 			pollLast() 
			檢索並刪除此列表的最後一個元素,如果此列表爲空,則返回 null 。  
E			pop() 
			從此列表表示的堆棧中彈出一個元素。  
void 		push(E e) 
			將元素推送到由此列表表示的堆棧上。  
E 			remove() 
			檢索並刪除此列表的頭(第一個元素)。  
E 			remove(int index) 
			刪除該列表中指定位置的元素。  
boolean		remove(Object o) 
			從列表中刪除指定元素的第一個出現(如果存在)。  
E 			removeFirst() 
			從此列表中刪除並返回第一個元素。  
boolean 	removeFirstOccurrence(Object o) 
			刪除此列表中指定元素的第一個出現(從頭到尾遍歷列表時)。  
E 			removeLast() 
			從此列表中刪除並返回最後一個元素。  
boolean 	removeLastOccurrence(Object o) 
			刪除此列表中指定元素的最後一次出現(從頭到尾遍歷列表時)。  
E 			set(int index, E element) 
			用指定的元素替換此列表中指定位置的元素。  
int 		size() 
			返回此列表中的元素數。  
Spliterator<E> 	spliterator() 
				在此列表中的元素上創建late-binding和故障快速 Spliterator 。  
Object[] 	toArray() 
			以正確的順序(從第一個到最後一個元素)返回一個包含此列表中所有元素的數組。  
<T> T[] 	toArray(T[] a) 
			以正確的順序返回一個包含此列表中所有元素的數組(從第一個到最後一個元素); 
			返回的數組的運行時類型是指定數組的運行時類型 

ArrayList和LinkedList的對比

ArrayList內部使用數組來實現List集合的特點,所以在使用訪問元素的時候可以使用數組自帶的下標來訪問元素,效果比較高。但是在ArrayList中插入元素的話,其他元素就會要移動位置,這種操作效率就會低一些

LinkedList內部使用鏈表來實現List集合的特點,所以在LinkList中進行元素插入的時候,效率比較高。但是如果要使用下標來訪問元素的話,LinkList的效率就會比較低,因爲鏈表中本來沒有下標,它的這個下標是模擬出來的。(ArrayList下標是數組自帶的)

//一個個遍歷
Node<E> node(int index) {
    // assert isElementIndex(index);
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}
private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
transient Node<E> first;
transient Node<E> last;
transient int size = 0;
//用transient關鍵字標記的成員變量不參與序列化過程。

時間戳

使用一個long類型數字來表示一個時間點。

public static long currentTimeMillis()

返回當前時間(以毫秒爲單位)。請注意,雖然返回值的時間單位爲毫秒,但該值的粒度取決於底層操作系統,並且可能較大。例如,許多操作系統以幾十毫秒爲單位測量時間。有關“計算機時間”和協調世界時間(UTC)之間可能出現的輕微差異的討論,請參閱類別Date的說明。

結果 :在1970年1月1日UTC之間的當前時間和午夜之間的差異,以毫秒爲單位。

插入和檢索測試對比

package com.zzb.day30;
import java.util.*;
public class ListTest {
	
	public static void main(String[] args){
		ListTest lt = new ListTest();
		lt.test();
	}
	public void test(){
		List list1 = new ArrayList();
		List list2 = new LinkedList();
		this.insertData(list1);
		this.insertData(list2);
		this.retrieveData(list1);
		this.retrieveData(list2);
	}
	public void insertData(List list){
		long a1 = System.currentTimeMillis();
		for(int i=0;i<500000;i++){
			list.add(0,1);
		}
		long a2 = System.currentTimeMillis();
		System.out.println(list.getClass()+":"+"插入耗時"+(a2-a1)+"毫秒");
	}

	public void retrieveData(List list){
		long a3 = System.currentTimeMillis();
		for(int i=0;i<500000;i++){
			Object obj = list.get(i);
		}
		long a4 = System.currentTimeMillis();
		System.out.println(list.getClass()+":"+"檢索耗時"+(a4-a3)+"毫秒");	
	}
}

在這裏插入圖片描述

Vector實現類的聲明:

public class Vector<E>
    extends AbstractList<E> implements List<E>, 
    RandomAccess, Cloneable, java.io.Serializable{
	//...
}

Vector這個實現類主要是實現List集合中的操作,並且保證了這些操作再多線程環境下也是安全的。這個類中對元素操作的實現方法上,都加入了關鍵字synchronization,這個關鍵字是給方法中的代碼進行加鎖的,加鎖後就能保證這個代碼的線程安全。

ArrayList和LinkedList裏面的方法都不是線程安全的,那麼在多線程的操作情況下,這兩個類來操作數據的話,可能會發生一些意想不到的情況(非線程安全)

例如:在一個線程中剛剛往ArrayList中存了一個數據,然後立刻在取出來,但是發現這個數據已經沒有了,因爲在我們往這個集合中存數據的時候,也有另外一個線程在操作這個集合,最後才導致了這麼一個現象。

那如果使用Vector的話,就會避免這種情況的發生,因爲Vector中進操作數據的方式都進行了加(synchronized),這樣以來,這個線程在操作這個集合中的方法時候,其他線程是用不了這個集合中的方法的。保證了第一個線程操作期間,不會有其他線程調用中國集合的方法來干擾自己的操作。

注意,Vector是犧牲了方法的執行效率,換來了方法執行的安全性。

自己模仿寫一個ArrayList

package com.zzb.day30;

public interface NewList {

	//在指定位置添加對象
	public void add(int index,Object obj);

	//在數據結構最後位置添加對象
	public void add(Object obj);
	
	//刪除指定位置上的對象
	public Object remove(int index);

	//修改指定位置上的數據
	public void set(int index,Object obj);

	//獲取指定位置上的數據
	public Object get(int index);

	//獲取當前數據結構當前的長度
	public int size();

	//清空所有的數據
	public void clear();
}

class NewArrayList implements NewList{
	
	private Object[] o;//聲明一個數組
	private int length = 3;//初始化數組長度
	private int size;//數組中數據的個數

	public NewArrayList(){
		o = new Object[length];
	}
	//在指定位置添加對象
	public void add(int index,Object obj){
		//System.out.print("調用  add(int index,Object obj)");
		if(index >size || index < 0){
			System.out.println("數組越界!!");
			return ;
		}
		if(size >= index){
			Object[] temp = new Object[length*2];
			System.arraycopy(o,0,temp,0,size);
			o = temp;
		}
		//方式一
		for(int i=size;i>index;i--){
			o[i] = o[i-1];
		}
		//方式二
		//System.arraycopy(o,index,o,index+1,size-index);

		o[index] = obj;
		size++;
	}

	//在數據結構最後位置添加對象
	public void add(Object obj){
		//System.out.print("調用  add(Object obj)");
		//數組滿了進行擴容操作
		if(size >= length){
			Object[] temp = new Object[length*2];
			//方式二
			System.arraycopy(o,0,temp,0,size);
			o = temp;
		}
		//常規操作
		o[size] = obj;
		size++;
	}
	
	//刪除指定位置上的對象
	public Object remove(int index){
		System.out.println("調用  remove(int index)");
		if(index>=size || index<0){
			return null;
		}
		for(int i=index;i<size-1;i++){
			o[i]=o[i+1];
		}
		o[--size] = null;
		return o[index];
	}

	//修改指定位置上的數據
	public void set(int index,Object obj){
		System.out.println("調用 set(int index,Object obj)");
		if( index<0||index>=size ){
			return ;
		}
		o[index] = obj;
	}

	//獲取指定位置上的數據
	public Object get(int index){
		System.out.println("調用 get(int index)");
		if(index >= size || index < 0){
			System.out.println("數組越界!!");
			return null;
		}
		return o[index];
	}

	//獲取當前數據結構當前的長度
	public int size(){
		System.out.println("調用size()");
		return size;
	}

	//清空所有的數據
	public void clear(){
		System.out.println("調用clear()");
		size = 0;
	}
}

class Test{
	public static void main(String[] args){
		Test t = new Test();
		
		NewList list = new NewArrayList();
		list.add("A");
		t.show(list);
		list.clear();
		t.show(list);
		list.add("B");
		list.add("C");
		list.add(0,"D");
		System.out.println(list.remove(0)+"被刪除!");
		list.set(0,"first");
		t.show(list);
	}
	
	public void show(NewList list){
		System.out.println("--------begin-------------");		
		for(int i=0;i<list.size();i++){
			System.out.println("\t"+list.get(i));
		}
		System.out.println("--------end---------------");
	}
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章