Java - 提高-源码(2) - ArrayList

Java8源码-ArrayList 今天开始学习ArrayList源码。参考的JDK版本为1.8。 相信大家对ArrayList的使用已经很熟悉了,但你真的了解ArrayList吗?ArrayList源码中注释的第一行是“Resizable-array implementation of the List interface”,意为“List接口的可变长数组实现”。ArrayList是如何实现可变长的?ArrayList有哪些私有... 阅读详情

ArrayList


源码对应JDK1.7

JDK1.7源码下载地址:JDK1.7源码

JDK 源码注释

Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)

 

The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation.

 

Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.

 

An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.

 

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more elements, or explicitly resizes the backing array; merely setting the value of an element is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the list. If no such object exists, the list should be "wrapped" using the Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

 

   List list = Collections.synchronizedList(new ArrayList(...));

 

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

 

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

 

This class is a member of the Java Collections Framework.

 

 

List接口的可调整大小数组实现。实现所有可选的列表操作,并允许所有元素,包括null。除了实现List接口之外,该类还提供了一些方法来控制用于内部存储列表的数组大小。 (这个类大致相当于Vector,除了它是不同步的。)

 

size,isEmpty,get,set,iterator和listIterator操作在恒定时间内运行。 add操作以分摊的恒定时间运行,即添加n个元素需要O(n)个时间。所有其他操作都在线性时间内运行(粗略地说)。与LinkedList实现相比,常数因子较低。

 

每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它总是至少与列表大小一样大。随着元素被添加到ArrayList,其容量会自动增长。增长政策的细节并未超出添加元素具有不变的摊销时间成本的事实。

 

在使用ensureCapacity操作添加大量元素之前,应用程序可以增加ArrayList实例的容量。这可能会减少增量重新分配的数量。

 

请注意,此实现不同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则它必须在外部同步。 (结构修改是任何添加或删除一个或多个元素的操作,或明确调整后备数组的大小;仅设置元素的值不是结构修改。)这通常通过同步某些自然封装名单。如果不存在这样的对象,则应使用Collections.synchronizedList方法“列出”列表。这最好在创建时完成,以防止意外的不同步访问列表:

 

   List list = Collections.synchronizedList(new ArrayList(...));

 

这个类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时候,结构上都会修改列表,除了通过迭代器自己的remove或add方法以外,迭代器将抛出ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在将来未定的时间冒着任意的,非确定性的行为冒险。

 

请注意,迭代器的故障快速行为无法得到保证,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬性保证。失败快速迭代器尽最大努力抛出ConcurrentModificationException。因此,编写一个依赖于此异常的程序是正确的:迭代器的快速失败行为应仅用于检测错误。

 

该类是Java集合框架的成员。

 

ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的。

实现了所有可选列表操作,并允许包括null在内的所有元素。

出了实现List接口外,此类还提供了一些方法用来操作内部用来存储列表的数组大小。

 

每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组大小。默认初始容量为10。

随着ArrayList中元素的增加,它的容量也会不断的自动增长。

在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,

所以如果我们知道具体业务数据量,在构造ArrayList时可以给ArrayList指定一个初始容量,这样就会减少扩容时数据的拷贝问题。

 

当然在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。

 

注意,ArrayList实现不是同步的。如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步。

所以为了保证同步,最好的办法是在创建时完成,以防止意外对列表进行不同步的访问:

List list =Collections.synchronizedList(new ArrayList(...));


首先记住结论:

a. ArrayList 是一个动态数组列表。

b. ArrayList 允许存储数据为空(null)

c. ArrayList 是非线程安全的,在多线程中使用:Collections.synchronizedList获取线程安全的对象。

d. ArrayList 是有序的(读取数据的顺序与存放数据的顺序一致) 

e. ArrayList 允许存储数据重复

f. ArrayList 默认长度10


ArrayList底层数组

/**
 * The array buffer into which the elements of the ArrayList are stored. 
 * The capacity of the ArrayList is the length of this array buffer.<br>
 * 阵列缓冲区,其中存储ArrayList的元素。 ArrayList的容量是此数组缓冲区的长度。
 * 
 */
private transient Object[] elementData;

/**
 * The size of the ArrayList (the number of elements it contains).<br>
 * ArrayList的大小(包含的元素数)。
 * 
 * @serial
 */
private int size;

elementData 就是ArrayList的容器


transient是Java关键字,为变量修饰符;

如果用transient声明一个实例变量,当对象存储时,它的值不需要维持,什么意思呢?

Java的serialization提供了一种持久化对象实例的机制。

当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。

transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

简单地说,增加transient 修饰符,就是取消该对象序列化。


为什么要取消序列化呢?

在序列化ArrayList的时候,ArrayList中的elementData未必是满的,比如说elementData长度为10,但是存放的元素只有3个,

那么是否有必要序列化整个elementData呢?显然是没有必要的,因此ArrayList中重写了writeObject()方法

/**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that is,
* serialize it).<br>
* 将 ArrayList 实例的状态保存到流中(即序列化它)。
* 
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
*             instance is emitted (int), followed by all of its elements
*             (each an <tt>Object</tt>) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
	// Write out element count, and any hidden stuff
	int expectedModCount = modCount;
	s.defaultWriteObject();

	// Write out array length
	s.writeInt(elementData.length);

	// Write out all elements in the proper order.
	for (int i = 0; i < size; i++)
			s.writeObject(elementData[i]);

	if (modCount != expectedModCount) {
			throw new ConcurrentModificationException();
	}

}

每次序列化时调用writeObject()方法,先调用defaultWriteObject()方法,序列化ArrayList中非transient的元素(也就是需要序列化)。

elementData不去序列化,接着遍历elementData[],只序列化数组中有的元素,这样的好处:

a. 加快了序列化的速度

b. 减小了序列化之后文件的大小


ArrayList构造函数

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

new ArrayList();之后可以看出,底层创建了一个长度为10的数组。elementData数组就是存放的容器。

/**

 * Constructs an empty list with an initial capacity of ten.

 */

public ArrayList() {

this(10);

}

 

/**

 * Constructs an empty list with the specified initial capacity.

 *

 * @param initialCapacity

 *            the initial capacity of the list

 * @throws IllegalArgumentException

 *             if the specified initial capacity is negative

 */

public ArrayList(int initialCapacity) {

super();

if (initialCapacity < 0)

throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);

this.elementData = new Object[initialCapacity];

}

 

/**

 * Constructs a list containing the elements of the specified collection, in

 * the order they are returned by the collection's iterator.

 *

 * @param c

 *            the collection whose elements are to be placed into this list

 * @throws NullPointerException

 *             if the specified collection is null

 */

public ArrayList(Collection<? extends E> c) {

elementData = c.toArray();

size = elementData.length;

// c.toArray might (incorrectly) not return Object[] (see 6260652)

if (elementData.getClass() != Object[].class)

elementData = Arrays.copyOf(elementData, size, Object[].class);

}

 


ArrayList成员变量

我们先看下,ArrayList中几个重要的成员变量

/**

 * Default initial capacity.<br>

 * 默认初始容量。

 */

private static final int DEFAULT_CAPACITY = 10;

 

/**

 * Shared empty array instance used for empty instances. <br>

 * 用于空实例的共享空数组实例。

 */

private static final Object[] EMPTY_ELEMENTDATA = {};

 

/**

 * 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 == EMPTY_ELEMENTDATA will be expanded to

 * DEFAULT_CAPACITY when the first element is added. <br>

 * ArrayList的元素存储在其中的数组缓冲区。<br>

 * ArrayList的容量是这个数组缓冲区的长度。<br>

 * 当添加第一个元素时,任何具有elementData ==

 * EMPTY_ELEMENTDATA的空ArrayList将展开为DEFAULT_CAPACITY。<br>

 *

 */

transient Object[] elementData; // non-private to simplify nested class

// access

 

/**

 * The size of the ArrayList (the number of elements it contains).<br>

 * ArrayList的大小(它包含的元素的数量)。

 *

 * @serial

 */

private int size;



ArrayList常用方法

在看下面的方法之前,我们先来看一个方法,System类中的 arraycopy()方法:
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

作用:
	从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
	从 src 引用的源数组到 dest 引用的目标数组,数组组件的一个子序列被复制下来。

参数说明:
	src - 源数组。
	srcPos - 源数组中的起始位置。
	dest - 目标数组。
	destPos - 目标数据中的起始位置。
	length - 要复制的数组元素的数量。 
来个Demo跑一下...
@Test
public void test() {

	// 创建一个长度为10的数组,并塞入对应值.
	String[] strArr = new String[10];
	for (int i = 0; i < strArr.length; i++) {
		strArr[i] = String.valueOf(i);
	}
	System.out.println(Arrays.toString(strArr));

	int size = strArr.length;

	// 模拟将index为2的数据删除
	int index = 2;

	// 向左移动的位数
	int numMoved = size - index - 1;

	/**
	 * 
	 * 从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束<br>
	 * 
	 * strArr:源数组<br>
	 * index+1:源数组中的起始位置---3<br>
	 * strArr:目标数组<br>
	 * index:目标数据中的起始位置---2<br>
	 * numMoved:要复制的数组元素的数量---7<br>
	 */
	System.arraycopy(strArr, index + 1, strArr, index, numMoved);

	System.out.println(Arrays.toString(strArr));

	strArr[--size] = null;

	System.out.println(Arrays.toString(strArr));
}

输出:
	[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
	[0, 1, 3, 4, 5, 6, 7, 8, 9, 9]
	[0, 1, 3, 4, 5, 6, 7, 8, 9, null]

add(E e)

源码:

/**
* Appends the specified element to the end of this list.<br>
* 将指定的元素追加到此列表的末尾。
*
* @param e
*            element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
	// 内部容量检查(判断是否需要扩容)
	ensureCapacityInternal(size + 1); // Increments modCount!!

	// 将数据,放在数组最后一位
	elementData[size++] = e;

	return true;
}

我们顺便深入看下ArrayList是怎么扩容的..

顺着ensureCapacityInternal()方法往下看

// 内部容量校验
private void ensureCapacityInternal(int minCapacity) {
	// list被修改次数
	modCount++;

	// overflow-conscious code
	// minCapacity为当前list中保存元素的数量+1
	// (当前容器保存数+1) - 容器(数组总长) 大于 0
	if (minCapacity - elementData.length > 0)
		// 扩容
		grow(minCapacity);
}

看下grow()方法

/**
* Increases the capacity to ensure that it can hold at least the number of
* elements specified by the minimum capacity argument.<br>
* 增加容量,以确保它至少容纳最小容量参数指定的元素数量。
* 
* @param minCapacity
*            the desired minimum capacity所需的最小容量
*/
private void grow(int minCapacity) {
	// overflow-conscious code
	// 旧数组的长度
	int oldCapacity = elementData.length;

	// 位移计算新新数组的长度
	int newCapacity = oldCapacity + (oldCapacity >> 1);

	// (新数组长度 - 所需最小长度) 小于 0
	if (newCapacity - minCapacity < 0)
			// 将最小长度赋值给新数组长度,说明最小长度够用
			newCapacity = minCapacity;

	// (新数组长度 - 数组最大长度) 大于 0,说明,新数组长度超出最大容量
	if (newCapacity - MAX_ARRAY_SIZE > 0)
			// 将所需最小长度数,传入进行计算
			newCapacity = hugeCapacity(minCapacity);

	// minCapacity is usually close to size, so this is a win:
	// Arrays.copyOf()方法,传入需要拷贝的数组和数组长度,返回新数组,完成数组的扩容
	elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
	// 最小长度数校验
	if (minCapacity < 0) // overflow
			throw new OutOfMemoryError();
	// 最小长度数 大于 最大长度限制,true:返回Integer最大数,false:返回数组最大限制数
	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
看到了嘛,底层扩容通过 Arrays.copyOf()方法

add(int index, E element)
源码:
/**
* Inserts the specified element at the specified position in this list.
* Shifts the element currently at that position (if any) and any subsequent
* elements to the right (adds one to their indices).
*
* 在该列表中的指定位置插入指定的元素。将当前位于该位置的元素(如果有)<br>
* 和任何后续元素(向其索引添加一个)移动。
*
* @param index
*            index at which the specified element is to be inserted<br>
*            指定元素要插入的索引
* @param element
*            element to be inserted<br>
*            要插入的元素
* 
* @throws IndexOutOfBoundsException
*             {@inheritDoc}
*/
public void add(int index, E element) {

	// index参数校验
	rangeCheckForAdd(index);

	// 内部容量检查(判断是否需要扩容)
	ensureCapacityInternal(size + 1); // Increments modCount!!

	// 使用arraycopy()方法,进行数组后移。
	// 目的是空出index的位置,插入element,并将index后的元素后移一个位置。
	System.arraycopy(elementData, index, elementData, index + 1, size - index);

	// 将元素插入index处
	elementData[index] = element;

	// ArrayList容量+1
	size++;
}

注释很详细了


addAll(Collection<? extends E> c)
源码:

/**
* Appends all of the elements in the specified collection to the end of
* this list, in the order that they are returned by the specified
* collection's Iterator. The behavior of this operation is undefined if the
* specified collection is modified while the operation is in progress.
* (This implies that the behavior of this call is undefined if the
* specified collection is this list, and this list is nonempty.)<br>
* 将指定集合中的所有元素追加到此列表的末尾,<br>
* 按照它们由指定集合的Iterator返回的顺序。<br>
* 如果在操作进行中修改了指定的集合,则此操作的行为是未定义的。<br>
* (这意味着如果指定的集合是此列表,并且此列表是非空的,则此调用的行为是未定义的。)<br>
*
* @param c
*            collection containing elements to be added to this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws NullPointerException
*             if the specified collection is null
*/
public boolean addAll(Collection<? extends E> c) {
	// 将集合转换为数组
	Object[] a = c.toArray();

	// 获取集合数组的长度
	int numNew = a.length;

	// ArrayList内部容量校验
	ensureCapacityInternal(size + numNew); // Increments modCount

	// 通过arraycopy()方法,将集合数组,复制到elementData中。
	System.arraycopy(a, 0, elementData, size, numNew);

	// 更新当前容量大小
	size += numNew;

	return numNew != 0;
}
注释写的都挺清楚的了..


get(int index)
源码:

@SuppressWarnings("unchecked")
E elementData(int index) {
	return (E) elementData[index];
}

/**
* Returns the element at the specified position in this list.<br>
* 返回此列表中指定位置的元素。
* 
* @param index
*            index of the element to return
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException
*             {@inheritDoc}
*/
public E get(int index) {

	// 检查索引是否在集合容器的范围内
	rangeCheck(index);

	//从数组中取出下标对应的数据
	return elementData(index);
}
这应该很好理解吧...


remove(Object o)
源码:

/**
* Removes the first occurrence of the specified element from this list, if
* it is present. If the list does not contain the element, it is unchanged.
* More formally, removes the element with the lowest index <tt>i</tt> such
* that
* <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
* (if such an element exists). Returns <tt>true</tt> if this list contained
* the specified element (or equivalently, if this list changed as a result
* of the call).<br>
*
* 从列表中删除指定元素的第一个出现(如果存在)。<br>
* 如果列表中不包含该元素,它将保持不变。<br>
*
* @param o
*            element to be removed from this list, if present
* @return <tt>true</tt> if this list contained the specified element
*/
public boolean remove(Object o) {

	if (o == null) {

	// 删除对象为null
	for (int index = 0; index < size; index++)
			// 循环取出集合中的数据,与null进行比较
			if (elementData[index] == null) {
					// 如果存在,删除对应下标的数据
					fastRemove(index);
					return true;
			}
	} else {

	// 删除对象不为null
	for (int index = 0; index < size; index++)
			// 循环取出集合中的数据与o进行比较
			if (o.equals(elementData[index])) {
					// 命中的话,删除对应下标的元素
					fastRemove(index);
					return true;
			}
	}
	return false;
}

/**
* Private remove method that skips bounds checking and does not return the
* value removed.<br>
* 专用remove方法跳过边界检查,并且不返回删除的值。
*/
private void fastRemove(int index) {
	modCount++;

	// 当前集合中存在元素的数量 - 下标位置数 - 1
	int numMoved = size - index - 1;
	if (numMoved > 0)
			// 通过arraycopy()方法,对数组进行复制,将index后的元素向前移动一个位置
			System.arraycopy(elementData, index + 1, elementData, index, numMoved);

	// 置空最后一个元素
	elementData[--size] = null; // Let gc do its work
}

注意:

通过上面几个通用的方法,我们可以看出,不论是add还是remove,ArrayList底层都是对数组进行操作。

要知道,操作数组进行扩容、复制十分浪费性能和效率。

所以,在开发中,要是能预先估算出ArrayList集合的大小,就通过ArrayList(int initialCapacity)设置初始容量。


举个栗子:

我们通过默认的ArrayList()构造方法创建对象,默认长度为10。

程序运行时,不断的add,这样子,数组的容量会一直自动扩容,一直操作数组拷贝,对性能和效率,是很大的浪费


ArrayList的优缺点

优点:

a. ArrayList 底层是数组实现,是一种随机访问模式,查询起来很快

b. ArrayList 顺序添加一个元素很方便

缺点:

a. 删除元素,会涉及到底层数组的复制,如果元素很多,会十分损耗性能

b. 插入指定位置元素,也会涉及到底层数组的复制,会十分损耗性能。

so,ArrayList比较适合顺序添加,随机访问的场景


ArrayList toArray()方法异常

我们先来看个Demo

public static void main(String[] args) {

	List<Integer> list = new ArrayList<Integer>();

	list.add(1);
	list.add(2);
	list.add(3);

	Integer[] integerArr = (Integer[]) list.toArray();

	System.out.println(Arrays.toString(integerArr));
}

输出结果:
Exception in thread "main" java.lang.ClassCastException: 
	[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
	at com.demo.list.list_1.TestList.main(TestList.java:17)

上面这段代码,看上去似乎没什么毛病,将ArrayList集合转换为数组并强转为Integer数组,然后输出数组

博主原文的意思是:出现错误是因为Java不支持向下转型。但是Java是支持向下转型的。感觉原博理解的有偏差

仔细思考一下,普通ArrayList的toArray()方法,返回的是Object[]数组类型,然后我们强转为Integer类型肯定会报错。

就是类型转换错误。

http://blog.youkuaiyun.com/lemon89/article/details/44727013

大致意思:list.toArray()返回的是Object数组,JVM不知如何盲目的?将object数组转换为Integer数组


那该如何解决呢?我们来看下面这个Demo,只是修改了两行代码:

public class TestList {

	public static void main(String[] args) {

	List<Integer> list = new ArrayList<Integer>();

	list.add(1);
	list.add(2);
	list.add(3);

	Integer[] integerA = new Integer[0]; 
	
	Integer[] integerArr = (Integer[]) list.toArray(integerA);

	System.out.println(Arrays.toString(integerArr));
	}

}
输出结果:
	[1, 2, 3]

大部分代码和上面是一样的,在调用toArray()方法的时候,我new了一个空的Integer[]数组,并传入了toArray()方法。

带参数的toArray()方法完整是这样的:

public <T> T[] toArray(T[] a) {
	if (a.length < size)
			// Make a new array of a's runtime type, but my contents:
			return (T[]) Arrays.copyOf(elementData, size, a.getClass());
	System.arraycopy(elementData, 0, a, 0, size);
	if (a.length > size)
			a[size] = null;
	return a;
}

可以看出,传参和返回参数,都是自定义泛型。

它会根据你传入的数组类型,进行转换,然后将转换完的数组返回给你。


参考资料:

http://www.cnblogs.com/skywang12345/p/3308556.html

http://blog.youkuaiyun.com/lemon89/article/details/44727013
http://www.cnblogs.com/xrq730/p/4989451.html

清华源pip install出现ERROR: Could not find a version that satisfies the requirement的解决方案 本文主要介绍了清华源pip install出现ERROR: Could not find a version that satisfies the requirement的解决方案,希望能对学习python的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 阅读详情

相关推荐

自监督学习与上下文赌博机融合:视觉决策中的协同优化与实战指南

在机器学习领域,自监督学习(Self-Supervised Learning)通过设计前置任务从无标注数据中学习通用表征,已成为解决标注数据稀缺问题的关键技术。其核心原理是利用数据自身的结构生成监督信号,训练编码器提取鲁棒特征。上下文赌博机(Contextual Bandits)作为强化学习的简化分支,专注于在给定上下文信息下做出单步最优决策,平衡探索与利用,广泛应用于推荐系统、广告投放等场景。将两者结合,构建端到端的协同训练框架,能让视觉表征的优化直接服务于最终的决策目标,同时利用自监督任务作为正则化项提

weixin_33721344的博客 520

ArrayList默认初始容量和扩容源码

版本:JDK 8 ArrayList默认初始容量 源码 The size of the ArrayList (the number of elements it contains). 数组列表的大小(包含元素的数量)。 Constructs an empty list with an initial capacity of ten. 构造一个初始容量为10的空列表。 总结 : ArrayList内部封装了一个默认长度为10的数组。 当超出长度时,集合内部会自动生成一个新的数组。 将原数组中的元素复制到新数

心态的博客 1216

鸿蒙OpenHarmony技术:【Docker编译环境】

OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。点击或者复制转到。表1Docker镜像介绍系统类型运行平台Docker镜像仓库标签标准系统(独立Docker环境)3.2小型系统(独立Docker环境)3.2轻量系统(独立Docker环境)3.2。

m0_62167422的博客 1445

java arraylist<>_Java ArrayList

Java ArrayList的构造方法和方法Constructor SummaryConstructorsConstructorDescriptionConstructs an empty list with an initial capacity of ten.ArrayList​(intinitialCapacity)Constructs an empty list with the spe...

weixin_35688434的博客 273

从零构建高精度温控系统:ADN8835的单电感拓扑与0.01℃稳定性实战解析

本文深入解析了如何利用ADN8835构建高精度温控系统,重点介绍了其创新的单电感拓扑架构如何实现0.01℃的长期稳定性。内容涵盖精密PCB布局、电源滤波设计,并详细阐述了针对不同热容负载的数字PID控制参数整定策略,为开发精密仪器和医疗设备提供了实战指南。

r2s3t4的博客 239

手把手教你为STM32设备生成自定义MAC地址(基于芯片ID的5种算法对比)

本文详细介绍了基于STM32芯片ID生成自定义MAC地址的5种算法,包括直接截取、异或折叠、CRC32哈希、自定义混合运算及SHA-256摘要。通过对比分析各算法的计算复杂度、唯一性及适用场景,帮助嵌入式开发者根据项目规模与资源,选择最合适的方案,确保设备MAC地址的唯一性与合规性。

weixin_29170327的博客 527

ArrayList源码分析(基于JDK8)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 为了复习Java集合相关知识点,对相关Java 集合源码进行走读学习,本篇文章记录对ArrayList(JDK1.8)源码走读的记录 一、ArrayList继承关系及全部源码 1、继承关系 2、全部源码 二、分段解读 1.ArrayList属性 //序列号 private...

lcgskycby的博客 561

Ubuntu视频播放器怎么选?VLC、mpv、SMPlayer硬解与字幕配置指南

在Linux系统中,视频播放体验取决于播放器、解码器与显卡驱动的协同。硬件解码通过VA-API或VDPAU将解码任务交给GPU,能显著降低CPU占用,解决4K高码率视频卡顿问题。对于Ubuntu用户,合理配置解码环境与播放器,可流畅播放HEVC、多音轨及ASS特效字幕视频。无论是日常观影、番剧追更还是家庭影院场景,选择合适的播放器并正确启用硬解,都是提升体验的关键。本文围绕Ubuntu平台,详解VLC、mpv、SMPlayer等播放器的安装、硬解配置与常见问题排查,帮助你在Linux上获得流畅的本地视频播放

weixin_33801856的博客 506

ArrayList详解,看这篇就够了

简介ArrayList 是 java 集合框架中比较常用的数据结构了。继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。成员变量ArrayList 底层是基于数组来实现容量大小动态变化的。

好好学java 19万+

高分SCI讨论部分必学AI写作套路!仅需五步结合GPT‑5辅助,让你的SCI论文更有说服力(附实用AI提示词)

对于很多写SCI论文的学术人来说,其实“讨论部分”才是最致命的,网上虽然有大量的写作技巧和模板提供参考,但往往让人眼花缭乱,还是不知道如何下手。即便是下手了,也很难兼顾学术性与可读性,实际上讨论部分的难点并不在于写,而在于你能研究结果说清楚。今天七哥教你借助GPT-5,用五步法结合精心设计的AI提示词,让你能在科学逻辑与语言表达上一次性解决“讨论部分”的结构、内容、润色和翻译问题,轻松写出符合高分SCI期刊要求的讨论段落。

智能AI让学术科研更容易 1330

DOTS 性能基石:为什么传统 Unity 代码难以满足现代游戏需求?(DOTS 系列教程 · 第1篇)

本文探讨了Unity游戏开发中的性能优化问题,指出性能问题不应在最后才考虑,而应贯穿整个开发过程。文章分析了性能问题的三大表现(渲染开销、物理模拟、游戏逻辑),并解释了依赖硬件升级的不可行性。重点剖析了传统Unity代码性能低下的六大根源:垃圾回收卡顿、编译器优化不足、多核利用不足、数据结构和代码缓存不友好、过度抽象等问题。最后指出Unity项目中常见的反模式,如主线程垄断、内存碎片化等,为后续学习DOTS高性能架构解决方案奠定基础。

分享知识,拥抱变化 151

HashMap源码分析

/* * %W% %E% * * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package java.util; import java.io.

xunileida的专栏 560

【华为OD机试真题 2025C卷】238、贪吃蛇 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

【华为OD机试真题 2025C卷】238、贪吃蛇 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS) 华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2025e卷,od机试,2025E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2025华为od,如何备战华为od,

正在更新最新华为OD机试2025B卷,提供OJ在线刷题 197

java1.8源码之ArrayList源码解读

一、ArrayList概述 1.1 ArrayList简介 ArrayList经常用,今天对它的源码探究一二。 一上来顶部有一大串注释,顶部注释参考了这篇博客内容如下: List接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括null在内的所有元素。除了实现List接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于Vector类,除了此类是不同步的。) ...

技术探求 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

ArrayList 扩容机制的源码剖析

在 Java 编程中,ArrayList是一个常用的集合类,它实现了List接口,底层基于数组实现。与普通定长数组不同,ArrayList能够根据元素的添加情况动态调整数组的大小,这就是其扩容机制。下面我们将深入剖析ArrayList扩容机制的源码。有的同学可能在别的地方听过一些ArrayList扩容,大部分会说ArrayList底层是数组结构的,默认长度为10,当数组加满后会自动扩容1.5倍。

2202_75481735的博客 1490

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java常用类介绍及源码阅读(ArrayList)

java.util 类 ArrayList<E> 继承关系: java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E> java.util.ArrayList<E> List接口的动态数组的实现。 ...

少说,多做。 7818

<Java八股文面试>ArrayList源码 | Iterator源码 | LinkedList和ArrayList对比

<Java八股文面试>ArrayList源码 | Iterator源码 | LinkedList和ArrayList对比

LXYDSF的博客 1908

java提高之ArrayList的源码分析

ArrayList简介 ArrayList核心源码 ArrayList源码分析 System.arraycopy()和Arrays.copyOf()方法 两者联系与区别 ArrayList核心扩容技术 内部类 ArrayList经典Demo ArrayList简介 ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元...

wjl31802的博客 567

arraylist索引从几开始_初探Java源码之ArrayList

作者:晨心w来源:https://www.jianshu.com/p/d49e4f5dc4c1前言在我们的日常开发中,集合类是我们基本上每个人都会用经常用到的东西,用着用着,突然有一天我心生好奇,那么java集合类的这些源码是什么呢?那么我打算接下来一个一个的查看一些常用的类源码争取达到心中有数的水平~~本文源码均来自Java 8总体介绍Collection接口是集合类的根接口,Java中没有提供...

weixin_29967445的博客 1652

java集合之ArrayList源码解析(java8)

说明:确保set的位置小于当前数组的长度(size)并且大于0,获取指定位置(index)元素,然后放到oldValue存放,将需要设置的元素放到指定的位置(index)上,然后将原来位置上的元素oldValue返回给用户。Vector是线程安全的,但是性能不及ArrayList,它们俩的底层实现都是数组。接口中全都是抽象的方法,而抽象类中可以有抽象方法,还可以有具体的实现方法,正是利用了这一点,让AbstractList是实现接口中一些通用的方法,而具体的类还可以添加自己独特的方法。

2501_90392287的博客 975

ArrayList源码解读

ArrayList 是对List接口的一种具体实现,属于单列集合类型。其内部数据结构基于动态数组实现,允许在运行时根据需要自动调整容量,从而实现了对元素的高效存储与访问。ArrayList 类继承自 AbstractList 抽象类,并且实现了 List 接口以及标记接口 Serializable。通过实现 Serializable 接口,ArrayList 集合的实例能够支持序列化过程,从而允许对象的状态被转换成可以存储或传输的形式,用于网络传输或保存到文件等。

记录大学四年代码 1166

【Java基础提高】说说ArrayList(五)

一、ArrayList    1.1简介    ArrayList是一个动态数组,它提供了动态的增加和减少元素。在使用时需要知道和注意以下几点: 在添加元素时,数组会随着新添加的元素逐渐增长。当元素数量达到数组容量时会带来数据向新数组里的拷贝,因此,在已知数组大小的情况下在其构造函数中指定ArrayList大小。或者在添加大量元素前,使用ensureCapacity()方法来

程序员小毛驴的博客 2043

Java集合类一:ArrayList(底层源码分析)

针对Java集合类ArrayList的底层源码分析、详解

Esther2020的博客 1904

java arraylist优点_JAVA提高十:ArrayList 深入分析

前面一章节,我们介绍了集合的类图,那么本节将学习Collection 接口中最常用的子类ArrayList类,本章分为下面几部分讲解(说明本章采用的JDK1.6源码进行分析,因为个人认为虽然JDK1.8进行了部分改动,但万变不离其宗,仍然采用的JDK1.6的引子进行的优化,因此学会了1.6对于1.8也就理解了)。一、ArrayList 的常见功能在分析ArrayList的源码前,我们先看下Arra...

weixin_29086203的博客 306

ArrayList源码解析

前言 在业务场景以及日常开发中,ArrayList往往是最频繁使用的List实现类,这由它的结构以及特性决定。ArrayList顾名思义,其底层是由数组实现,因此查询时间复杂度是常数级别的,再加之有一些小优化,查询速度会更快。由于其底层是数组实现,插入和删除都是O(n)级别的。业务场景往往是多读少写的,因此ArrayList就很适合。下面就来解析ArrayList的源码以及常见方法的实现 本篇文章基于JDK8 正文 1. 成员变量 首先看一下它的成员变量 DEFAULT_CAPACITY = 10

matrixZCL的博客 2150

Java集合源码分析(一)ArrayList

Java集合源码分析(一)ArrayList 阅读目录(Content) 一、ArrayList简介 1.1、ArrayList概述 1.2、ArrayList的数据结构 二、ArrayList源码分析 2.1、继承结构和层次关系 2.2、类中的属性 2.3、构造方法 2.4、核心方法   2.4.1、add()方法(有四个)   2.4.2...

weixin_30243533的博客 180

JAVA集合源码学习——ArrayList

JAVA集合源码学习——ArrayList ArrayList概述 1)ArrayList是基于长度可动态增长的数组实现List接口的java集合类 2)ArrayList类内部维护者一个动态可再分配的Object[]数组,每一个类对象都有一个capacity属性,表示所封装的Object[]对象数组的长度,但往ArrayList添加元素时,该属性值会自动增加,体现了动态的特点 3)如果要往Arr...

优快云advancer的博客 302
上一篇: 并发基础_5_并发_ThreadLocal
下一篇: Java - 提高-源码(3) - LinkedList
Simba_cheng
博客等级 码龄11年 250粉丝 203原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值