JDK源码分析(3)之 ArrayList 相关 (2)

同时在ArrayList进行数组操作的时候都会进行安全检查,包括下标检查和容量检查

// 容量检查 public void ensureCapacity(int minCapacity) { int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // any size if not default element table ? 0 // larger than default for default empty table. It's already // supposed to be at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } 四、迭代方式 1. 随机访问

由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。

for (int i=0, len = list.size(); i < len; i++) { String s = list.get(i); } 2. 迭代器遍历

这其实就是迭代器模式

Iterator iter = list.iterator(); while (iter.hasNext()) { String s = (String)iter.next(); } 3. 增强for循环遍历

这其实是一个语法糖

for (String s : list) { ... } 4. 增强for循环遍历的实现

对于ArrayList

public void test_List() { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); for (String s : list) { System.out.println(s); } }

使用javap -v 反编译

Code: stack=2, locals=4, args_size=1 ... 27: invokeinterface #7, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator; 32: astore_2 33: aload_2 34: invokeinterface #8, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z ...

这里可以很清楚的看到,其实是通过Iterator迭代器实现的

对于Array

public void test_array() { String[] ss = {"a", "b"}; for (String s : ss) { System.out.println(s); } }

使用javap -v 反编译

Code: stack=4, locals=6, args_size=1 0: iconst_2 1: anewarray #2 // class java/lang/String 4: dup 5: iconst_0 6: ldc #3 // String a 8: aastore 9: dup 10: iconst_1 11: ldc #4 // String b 13: aastore 14: astore_1 15: aload_1 16: astore_2 17: aload_2 18: arraylength 19: istore_3 20: iconst_0 21: istore 4 // 将一个数值从操作数栈存储到局部变量表 23: iload 4 // 将局部变量加载到操作栈 25: iload_3 26: if_icmpge 49 29: aload_2 30: iload 4 32: aaload 33: astore 5 35: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream; 38: aload 5 40: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 43: iinc 4, 1 46: goto 23 49: return

这里只能到导致看到是在做一些存取操作,但也不是很清楚,所以可以直接反编译成java代码

public void test_array() { String[] ss = new String[]{"a", "b"}; String[] var2 = ss; int var3 = ss.length; for(int var4 = 0; var4 < var3; ++var4) { String s = var2[var4]; System.out.println(s); } }

现在就能很清楚的看到其实是通过随机存储(下标访问)的方式实现的;

五、fail-fast机制

fail-fast是说当并发的对容器内容进行操作时,快速的抛出ConcurrentModificationException;但是这种快速失败操作无法得到保证,它不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常。所以我们程序的正确性不能完全依赖这个异常,只应用于bug检测。

protected transient int modCount = 0; private void checkForComodification() { if (ArrayList.this.modCount != this.modCount) throw new ConcurrentModificationException(); }

在ArrayList的Iterator和SubList中,每当进行内存操作时,都会先使用checkForComodification来检测内容是否已修改。

总结

ArrayList整体来看就是一个更加安全和方便的数组,但是他的插入和删除操作也实在是蛋疼,对于这一点其实可以通过树或者跳表来解决。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzzxjs.html