ArrayList引发的一系列问题

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: ArrayList引发的一系列问题

List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。)

构造方法摘要

ArrayList() 构造一个初始容量为 10 的空列表。
ArrayList(Collection<? extends E> c) 构造一个包含指定
collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表。

ArrayList 每次扩容都以当前数组大小的 1.5 倍去扩容

ArrayList 是非线程安全的,Vector 是线程安全的。

现在看一下小伙伴的刁钻问题

请在此添加图片描述

插入源码

 /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

当对象实现序列化接口,但部分属性不希望在网络操作的时候,可由关键字transient修饰。那么这行ArrayList是如何解决的?

请在此添加图片描述

请在此添加图片描述

?????

经过资料查询:

elementData里面不是所有的元素都有数据,因为容量的问题,elementData里面有一些元素是空的,这种是没有必要序列化的。ArrayList的序列化和反序列化依赖本身的writeObject和readObject方法来实现。可以避免序列化空的元素

 /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
   
   
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
   
   
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
   
   
                a[i] = s.readObject();
            }
        }
    }

被transient关键字修饰的变量真的不能被序列化吗?

import java.io.Externalizable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

/**
* @descripiton Externalizable接口的使用

*
*/public class ExternalizableTest implements Externalizable {
   
   

private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";

@Override
public void writeExternal(ObjectOutput out) throws IOException {
   
   
out.writeObject(content);
}

@Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
   
   
content = (String) in.readObject();
}

public static void main(String[] args) throws Exception {
   
   
ExternalizableTest et = new ExternalizableTest();
ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
new File("test")));
out.writeObject(et);

ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
"test")));
et = (ExternalizableTest) in.readObject();
System.out.println(et.content);

out.close();
in.close();
}
}

对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关

原文链接:

http://www.codeceo.com/article/java-transient-keyword.html

请在此添加图片描述

插入源码:

 public E remove(int index) {
   
   
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

clear to let GC do its work这段代码让他耿耿于怀

待我请教高人后解答

问题二:hashMap一直put元素会怎么样?

/**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */
    static final int MAXIMUM_CAPACITY = 1 << 30;

这里的Hashmap的最大容量是1左位移30

那么循环put次数大于此数值呢?

static final int MAXIMUM_CAPACITY = 1 << 30;//极限值(超过这个值就将threshold修改为Integer.MAX_VALUE(此时桶大小已经是2的31次方了),表明不进行扩容了)
final Node<K,V>[] resize() {
   
   
        Node<K,V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;
        int newCap, newThr = 0;
        if (oldCap > 0) {
   
   
            if (oldCap >= MAXIMUM_CAPACITY) {
   
   
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }
        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;
        else {
   
                  // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
        }
        if (newThr == 0) {
   
   
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                      (int)ft : Integer.MAX_VALUE);
        }

问题待解答!!!

目录
相关文章
|
2月前
|
索引
ArrayList
ArrayList
31 0
|
8月前
|
安全 Java
你对ArrayList了解多少?
你对ArrayList了解多少?
24 0
|
8月前
|
安全 Java
|
10月前
详解ArrayList
1.数据结构 底层使用Object类型的数组实现,线程不安全,添加元素时如果内存已满则会开辟新空间,将原数组copy过去。
73 0
|
10月前
|
算法
深入理解ArrayList(四)
深入理解ArrayList(四)
62 0
|
10月前
|
Java 测试技术 索引
深入理解ArrayList(三)
深入理解ArrayList(三)
51 0
|
10月前
|
Java 开发者
深入理解ArrayList(二)
深入理解ArrayList(二)
57 0
|
10月前
深入理解ArrayList(一)
深入理解ArrayList(一)
48 0
|
10月前
|
存储 设计模式 算法
ArrayList和LinkedList
介绍ArrayList和LinkedList
|
安全 Java 程序员
ArrayList使用详解
ArrayList使用详解
154 0
ArrayList使用详解