第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後帥氣小夥,良好的開發習慣;獨立思考的能力;主動並且善於溝通
簡書部落格: https://www.jianshu.com/u/c785ece603d1
結語
- 下面我將繼續對 其他知識 深入講解 ,有興趣可以繼續關注
- 小禮物走一走 or 點贊