第56節:ArrayList,LinkedList和String

標題圖
import java.util.ArrayList; public class Demo{ public static void main(String[] args) throws Exception { ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); for(Integer integer : arrayList){ arrayList.remove(1); } } }
異常的出現:

描述
Exception in thread "main" java.util.ConcurrentModificationException
如果換為
for(Integer integer : arrayList){ System.out.println(arrayList.remove(0)); }
那麼顯示臺為:

描述
1 Exception in thread "main" java.util.ConcurrentModificationException
這樣的話把 arrayList.remove( )
中的數字改為 0, 1, 2, 的話,顯示臺會出現 1, 2, 3, 的.
import java.util.ArrayList; public class Demo { public static void main(String[] args) throws Exception{ ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(1); arrayList.add(2); arrayList.add(3); for(Integer integer : arrayList){ System.out.println(arrayList.remove(0)); break; } } }
這樣控制檯顯示為:
// 顯示為 1 1
集合是用來儲存一些變數
Collection
的一些常見方法:
size() isEmpty(() contains(Object) toArray() toArray(T[]) add(E) remove(Object) containsAll(Collection<?>) addAll(Collection<? extends E>) retainAll(Collection<?>) clear() stream()
ArrayList
// 原始碼: public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable // 再次往上走 public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> // 再次往上走 public abstract class AbstractCollection<E> implements Collection<E>
在上述程式碼中,有可能看到的異常會有所不理解。因為無法在迭代的過程中進行修改,只能讀而已。因為是一個臨時的儲存空間。如果要用可以如下:
import java.util.ArrayList; import java.util.Iterator; public class Demo { public static void main(String[] args) throws Exception{ ArrayList<Integer> arrayList = new ArrayList<>(); arrayList.add(11); arrayList.add(21); arrayList.add(31); //for(Integer integer : arrayList){ //System.out.println(arrayList.remove(0)); //break; //} System.out.println(arrayList.size()); for (int i = 0,length = arrayList.size(); i <length ; i++) { System.out.println(i); arrayList.remove(0); } System.out.println(arrayList.size()); } }
public class Demo { Object[] object2; public static Object[] objects = {}; public void test(){ System.out.println(objects == object2); } public static void main(String[] args) throws Exception{ Demo n = new Demo(); System.out.println(n.object2); System.out.println(objects); new Demo().test(); } }

描述
在集合初始化時,要儘量指定集合的初始值大小,在 ArrayList
中,要多多使用 ArrayList(int initialCapacity)
的初始化.
ArrayList
中的記憶體地址是連續的,它存放的是連續的,如 1,2,3,4,5
等,可以通過索引找到自己想要,因為是連續的,所以馬上就可以找到自己想要的了.
在 LinkedList
中是處於不同的記憶體地址的,每個元素儲存的空間有個檔案指標是指向下一個元素的,只有當它進行迭代後,才能找到.
Class ArrayList<E>
java.lang.Object
->java.util.AbstractCollection<E>
->java.util.AbstractList<E>
->java.util.ArrayList<E>
所有實現的介面:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
知道的子類:
AttributeList, RoleList, RoleUnresolveList
完整結構:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
ArrayList
是可以調整陣列大小,實現 List
的介面. ArrayList
是基於實現動態資料的資料結構哦,進行隨機訪問比較容易,用 get
和 set
方法~

描述
Class LinkedList<E>
java.lang.Object
->java.util.AbstractCollection<E>
->java.util.AbstractList<E>
->java.util.AbstractSequentialList<E>
->java.util.LinkedList<E>
引數型別 E
為這個集合中要保持的資料型別.
完整結構:
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable

描述
LinkedList
是使用了迴圈雙向連結串列資料結構, LinkedList
連結串列是由 元素內容,前驅表和後驅表, 一系列表項連線而成的.
連結串列內是由一個 header
的表項是作為連結串列的開始,也同樣有連結串列的結尾.在連結串列中表項頭 header
的後驅表項就是連結串列中第一個元素,而表項 header
的前驅就是連結串列的最後一個元素.
陣列:陣列是連續儲存的,所以它的索引非常的快,在記憶體中賦值和修改也很容易.
int[] arr = new int[3];
int[] arr = new int[3] {1,2,3};
int[] arr = {1,2,3,4};
在陣列中一定存在著它不好的缺點,因為如果在我們不知道陣列的長度情況下會很麻煩,宣告陣列一定要指定它的長度,如果這個長度太長,就會導致浪費記憶體,如果過短的情況下又會導致資料溢位的結果.
這時上帝建立了 ArrayList
的類,使用這個類就必須要進行引用,然後繼承介面,在 ArrayList
物件的大小是可以動態改變的,不像陣列那樣死板固定化,可以自由擴充套件和收縮儲存的資料.
建立物件:
ArrayList arrayList = new ArrayList();
新增資料等等:
arrayList.add("dashucoding");
在 LinkedList
都是指標指向下一個元素,如果中間有進行刪減,那麼後面的元素會提前到前面空缺的位置,後面的也一樣.所以 LinkedList
比較麻煩的, LinkedList
是基於連結串列的資料結構哦~
總結 LinkedList
和 ArrayList
ArrayList
比較好訪問 get
和 set
,而 LinkedList
比較好增加和刪除 add
和 remove
.都是為了防止移動資料嘛,移動就會比較麻煩嘛~
import java.util.LinkedList; public class Demo{ public static void main(String[] args){ LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(1); } }
// add方法 public boolean add(E e){ // 插入到最後一位 linkLast(e); // 返回為true return true; }
// 最尾 void linkLast(E e){ // last賦給l, 初始Last為空 final Node<E> l = last; final Node<E> newNode = new Node<>(1,e,null); // 更新Last指標指向新的節點 last = newNode; if(l == null){ // 如果為第一次插入,就將first指標指向第一個節點 first = newNode; }else{ // 如果有了頭節點,就將l指標的next指向新節點 l.next = newNode; } // 連結串列大小加一 size++; // 修改次數加一 modCount++; }
// LinkedList$Node.class 內部類,靜態類 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; } } // since 1.6 public Iterator<E> descendingIterator(){ return new DescendingIterator(); }
transient Node<E> last;
public int size(){ return size; }
ArrayList<E>
public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } // 構造一個空的物件陣列 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 呼叫方法 ensureCapacityInternal(size+1); // list內部日期是否有多餘空間
if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA){ minCapacity=Math.max(DEFAULT_CAPACITY,minCapacity); } ensureExplicitCapacity(minCapacity); // 記錄下資料的修改次數 modCount++; if(minCapacity - elementData.length > 0) grow(minCapacity);
private void grow(int minCapacity){ int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if(newCapacity - minCapacity < 0) newCapacity = minCapacity; if(newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData,newCapacity); }

描述

描述

描述

描述
package day1; public class Demo { public static Object[] objects = {}; public static void main(String[] args) throws Exception{ System.out.println(objects.getClass()); } }

描述
package day1; public class Demo { public static Object[] objects = {}; public static void main(String[] args) throws Exception{ System.out.println((Object)objects.getClass()); } }
不變:

描述
public class Demo { public static Object[] objects = {}; public static void main(String[] args) throws Exception { System.out.println((Object)objects == (Object)objects.getClass()); } } // false
public class Demo { public static Object[] objects = {}; public static void main(String[] args) throws Exception{ System.out.println((Object)objects == (Object)Object[].class); } } // false
package day1; public class Demo { String string = "dashucoding"; public static void main(String[] args) throws Exception{ String string = "dashucoding"; System.out.println(string.getClass()==String.class); } } // 為true
public static Object[] objects = {}; objects.getClass() == Object[].class objects instanceof Object[]
String
Class String
java.lang.Object
java.lang.String
public final class String extends Object implement Serializable, Comparable<String>, CharSequece
String
類表示為字串,所有的字串都被實現為此類的例項,字串是不可以變的,它們的值在建立後不可以改變,字串緩衝區是支援可變的字串的.
字串:
String str = "dashucoding";
等於:
char data[] = { 'da', 'shu', 'coding'}; String str = new String (data);
例子:
public class Demo { public static void main(String[] args) throws Exception{ System.out.println("cat"); // cat String a = "mouse"; System.out.println("cat" + " " + a); // cat mouse String c = "cat".substring(2,3); System.out.println(c); // s String d = a.substring(1, 2); // o System.out.println(d); } }

描述
String
類可以用於比較字串,搜尋字串,提取字串等等,各種方法,字串的連線可以用 +
這個運算子,但是 Java
提供了 StringBuilder
和 StringBuffer
類,通過用 append
方法實現連線,字串方法還可以用 toString
的方法進行字串的轉換.
丟擲異常:如果字串傳值為 null
的時候,會丟擲 NullPointerException
.
public String toString()
toString
用來返回物件的字串表現形式
Class StringBuffer
java.lang.Object
java.lang.StringBuffer
public final class StringBuffer extends Object implements Serializable, CharSequence
StringBuffer
執行緒安全,是可變的字元序列,字串在緩衝區中可以修改,在 StringBuffer
中是常常用到 append
方法和 insert
的方法.通過這些方法進行將資料轉換為字串,把字串載入到字串緩衝區中.
append()
的方法是用於在緩衝區中的末尾新增這些字元,和 insert()
方法是將資料新增到指定的位置.
案例:
比如在字元緩衝區中已經有物件 dashu
用 a
進行表示,然後呼叫 a.append("coding");
,而 insert()
插入的方法也容易,引數兩個,第一個為插入的位置,第二個為插入的資料而已.
注意每個字串緩衝區是由屬於它自己的容量的,如果內部的緩衝區溢位,就會導致自動變大,如果夠用,就不會被分析新的. StringBuffer
通常用單個執行緒字串緩衝區的地方.
Class StringBuilder
java.lang.Object
java.lang.StringBuilder
public final class StringBuilder extends Object implements Serializable, CharSequence
StringBuilder
也是一個可變的資產.同樣也有 append()
方法和 insert()
的方法,有了 StringBuilder
的出現, StringBuffer
都靠邊了.但是如果有多執行緒就不能夠安全的使用了,就要改換使用 StringBuffer
了.
往後餘生,唯獨有你
簡書作者:達叔小生
90後帥氣小夥,良好的開發習慣;獨立思考的能力;主動並且善於溝通
簡書部落格: ofollow,noindex">https://www.jianshu.com/u/c785ece603d1
結語
- 下面我將繼續對 其他知識 深入講解 ,有興趣可以繼續關注
- 小禮物走一走 or 點贊