前言
List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。
本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。
关于的Set的博客文章如下:
关于HaseMap的博客文章如下:
- Java进阶(HashMap)——面试时HashMap常见问题解读 & 结合源码分析
- Java进阶(ConcurrentHashMap)——面试时ConcurrentHashMap常见问题解读 & 结合源码分析 & 多线程CAS比较并交换 初识
其他相关的List的文章合集如下:
目录
引出
1.ArrayList如何扩容,1.5倍;
2.ArrayList如何拷贝,深拷贝,浅拷贝;
3.ArrayList的增加或者删除效率低,arraycopy方法;
4.指定长度创建ArrayList对象,避免频繁扩容;
5.线程安全的ArrayList集合:Collections.synchronizedList;
6.LinkedList 和 ArrayList 该如何选择:ArrayList增删效率低,查询效率高;LinkedList 查询效率低,增删效率高
7.Vector 集合和 ArrayList 区别:Vector扩容机制为原始的2倍,线程安全;
ArrayList 如何扩容的?/ArrayList的大小是如何自动增加的?
ArrayList初始化的时候,若没有给定长度,则默认调用无参构造
此处elelmentData为ArrayList底层数组,后面DEFAULTCAPACITY_EMPTY_ELEMENTDATA 为常量数组初值为空,即长度为0
1.add添加第一个元素
当执行add方法添加第一个元素时,执行下面的代码
此处涉及到两条代码:
- ensureCapacityInternal方法内会调用calculateCapacity方法,此处才是赋予数组长度为10
ensureCapacityInternal 方法
calculateCapacity方法
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果数组是空的
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//返回数组的容量,DEFAULT_CAPACITY=10
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
此时集合可以添加默认的10个元素
2.添加第11个元素时
当添加第11个元素时,ensureExplicitCapacity方法中,minCapacity为11,而原数组长度为10,所以if结构进入grow方法-扩容核心方法
ensureExplicitCapacity方法
grow方法-扩容核心方法
private void grow(int minCapacity) {
// overflow-conscious code
//把旧的长度赋值给oldCapacity
int oldCapacity = elementData.length;
//新的长度就=旧的长度*1.5
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//按照新的长度复制出一个新的数组
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
-
oldCapacity赋值为原数组长度,为10 ,newCapacity赋值为原长度1.5倍,即15
-
调用复制数组方法,将之前的数组复制到新的数组中,并将需要添加的元素加到数组最后一位,完成扩容!
如何复制某个ArrayList到另一个Arraylist中去?
重写clone方法,ArrayList克隆
厘清概念:深浅拷贝
Java进阶(4)——结合类加载JVM的过程理解创建对象的几种方式:new,反射Class,克隆clone(拷贝),序列化反序列化
浅拷贝:虽然返回一个元素一样的ArrayList,复制的是元素的引用,即其中一个改变了元素,另一个也会跟着改变
两个集合中间存储了同一份元素的引用
例如:
深拷贝:重写clone方法,利用迭代器iterator或遍历集合,重新创建引用对象,逐个添加
例如:
复制的方法
list.clone()
clone.addALl(list);
Collections.copy(clone,list);
在索引中ArrayList的增加或者删除某个对象的运行过程?效率很低吗?解释一下为什么?
效率确实低
效率是很低的,因为ArrayList无论是增加或者删除某个对象,我们都要通过对数组中的元素进行移位来实现。
- 增加元素时,我们要把要增加位置及以后的所有元素都往后移一位,先腾出一个空间,然后再进行添加。
- 删除某个元素时,我们也要把删除位置以后的元素全部元素往前挪一位,通过覆盖的方式来删除。
而这种移位就需要不断的arraycopy,是很耗时间的,所以效率自然也很低。
源码arraycopy方法
增加元素时
删除元素时
现在我有一个很大的数组需要拷贝,原数组大小是 5k,请问如何快速拷贝?
指定长度创建ArrayList对象,避免频繁扩容
如何获得一个线程安全的ArrayList集合?
Collections.synchronizedList
List<Object> datas = Collections.synchronizedList(new ArrayList<>());
- 1
源码分析
从源码可以看到集合操作都加了synchronized 关键字,保证了在同一时刻,数组和链表只会被一个线程所修改。
LinkedList 和 ArrayList 该如何选择?
选择原则
- ArrayList 底层为数组,在增加和删除元素时会频繁的调用arraycopy,所以查询效率高,增删效率低
- LinkedList 底层为链表,故查询效率低,但增删效率高。
LinkedList源码node节点
- item 为当前元素
- next指向下一个元素,若为最后一个则为null
- prev指向上一个元素,若为第一个则为null
Vector 集合
- vector 和 ArrayList 基本一样
- 区别在于 vector扩容机制为原始的2倍,ArrayList为之前的1.5倍
- vector 是线程安全的,ArrayList是非线程安全的
总结
1.ArrayList如何扩容,1.5倍;
2.ArrayList如何拷贝,深拷贝,浅拷贝;
3.ArrayList的增加或者删除效率低,arraycopy方法;
4.指定长度创建ArrayList对象,避免频繁扩容;
5.线程安全的ArrayList集合:Collections.synchronizedList;
6.LinkedList 和 ArrayList 该如何选择:ArrayList增删效率低,查询效率高;LinkedList 查询效率低,增删效率高
7.Vector 集合和 ArrayList 区别:Vector扩容机制为原始的2倍,线程安全;
文章目录
前言
ArduPilot 支持基于本机的圆柱形(“TinCan”)和多边形和/或圆柱形、包容和/或排除区域。在任务计划器中的计划屏幕下,可以轻松定义包容和排斥栅栏,并使用下拉框中的栅栏项目将其加载到自动驾驶仪中,就像计划任务或集结点一样。
有些飞行器还有最大和/或最小高度限制。某些飞行模式会尝试自动防止超出这些限制,如果超出限制,所有模式下都会宣布突破栅栏。
一旦突破栅栏,将采取可选择的行动。
1 通用设置
设置 FENCE_ENABLE = 1 可启用围栏。这将启用任何已设置的栅栏,但 ALT_MIN 栅栏除外,该栅栏必须通过任何栅栏启用方法(GCS 信息、飞机上的自动启用、RC 开关)启用。
将 FENCE_ACTION = 设置为你希望的破坏动作。这些将根据飞行器类型而有所不同。请参阅上面的栅栏破坏动作(Fence Breach Actions)。
将 FENCE_OPTIONS 设置为 “1”,以防止突破栅栏后改变模式,直到飞行器返回栅栏边界内(仅限固定翼,旋翼机/无人车在突破栅栏时不允许改变模式)。
将 FENCE_ALT_MAX = 设为所需的高度限制(以米为单位)。这在无人车中不可用。
设置 FENCE_MARGIN = 为飞行器为防止突破而必须保持的与围栏水平边界的距离。
将 FENCE_ALT_MIN 设置为最小突破高度边界。
设置 FENCE_AUTOENABLE =(仅限固定翼)以允许在某些飞行器条件下(如解锁或起飞时)自动启用栅栏(与 FENCE_ENABLE 不同)。值为 0 则禁用此功能。如果启用此功能,FENCE_ENABLE 将被忽略。仅建议使用 FENCE_AUTOENABLE = 3(在 ARM 时启用)。由于 “1”或 “2”功能可能会在遏制方面产生不良结果,因此很快就会被淘汰。
FENCE_RET_RALLY 允许返回最近的集结点(见:集结点)(如果已加载),而不是返回 “主页”。
设置 FENCE_TYPE = 是一个位图设置,用于启用各种栅栏类型: 最小或最大高度、“本垒”周围的简单 CIRCLE 锡罐或 POLYGON 栅栏。POLYGON 栅栏还必须通过地面控制站的栅栏列表加载才能激活。有关圆柱形栅栏(Cylindrical Fence)以及包含和排除栅栏(Inclusion and Exclusion Fences)的详细设置,请参阅下文。
!Note
多边形围栏类型包括包含/排除围栏列表中指定的圆形围栏。以家庭为中心的简单 CIRCLE 栅栏是一种独立的栅栏。如果设置了高度,Rover 会忽略高度。
FENCE_TYPE 的默认值为:
- 无人车:圆环和多边形;
- 旋翼飞机:ALT MAX、CIRCLE 和 POLYGON;
- 固定翼:多边形。
详细资料
2 围栏类型
class="table-box"> TYPE OF FENCE | FENCE_TYPE bit | PLANE | COPTER | ROVER |
Global Maximum Altitude
| 0 | X | X | |
Cylindrical (“TinCan”)
| 1 | X | X | X |
Inclusion/Exclusion Zones
| 2 | X | X | X |
Global Minimum Altitude
| 3 | X |
评论记录:
回复评论: