首页 > 其他分享 >ArrayList与顺序表

ArrayList与顺序表

时间:2024-08-28 15:22:21浏览次数:10  
标签:顺序 int ArrayList elementData list add minCapacity

1.线性表

         线性表( linear list ) 是 n 个具有 相同特性的数据元素 的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列..         线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物 理上存储时,通常以数组和链式结构的形式存储。

2.顺序表

顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成 数据的增删查改。

3. ArrayList简介

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:

说明 】 1. ArrayList 是以泛型方式实现的,使用时必须要先 实例化 2. ArrayList 实现了 RandomAccess 接口,表明 ArrayList 支持随机访问 3. ArrayList 实现了 Cloneable 接口,表明 ArrayList 是可以 clone的 4. ArrayList 实现了 Serializable 接口,表明 ArrayList 是 支持序列化 的 5. 和 Vector 不同, ArrayList 不是线程安全的,在单线程下可以使用,在多线程中可以选择 Vector 或者 CopyOnWriteArrayList 6. ArrayList 底层是一段连续的空间,并且可以 动态扩容 ,是一个动态类型的顺序表

3.1 ArrayList的构造

public static void main ( String [] args ) { // ArrayList 创建,推荐写法 // 构造一个空的列表 List < Integer > list1 = new ArrayList <> (); // 构造一个具有 10 个容量的列表 List < Integer > list2 = new ArrayList <> ( 10 ); list2 . add ( 1 ); list2 . add ( 2 ); list2 . add ( 3 ); // list2.add("hello"); // 编译失败, List<Integer> 已经限定了, list2 中只能存储整形元 素 // list3 构造好之后,与 list 中的元素一致 ArrayList < Integer > list3 = new ArrayList <> ( list2 ); // 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难 List list4 = new ArrayList (); list4 . add ( "111" ); list4 . add ( 100 ); }

 

 

 3.2ArrayList的遍历

for 循环 + 下标、 foreach 、使用迭代器
public static void main ( String [] args ) { List < Integer > list = new ArrayList <> (); list . add ( 1 ); list . add ( 2 ); list . add ( 3 ); list . add ( 4 ); list . add ( 5 ); // 使用下标 +for 遍历 for ( int i = 0 ; i < list . size (); i ++ ) { System . out . print ( list . get ( i ) + " " ); } System . out . println (); // 借助 foreach 遍历 for ( Integer integer : list ) { System . out . print ( integer + " " ); } System . out . println (); //迭代器 Iterator < Integer > it = list . listIterator (); while ( it . hasNext ()){ System . out . print ( it . next () + " " ); } System . out . println (); } 注意: 1. ArrayList 最长使用的遍历方式是: for 循环 + 下标 以及 foreach 2. 迭代器是设计模式的一种

3.3ArrayList的扩容机制 

每个ArrayList都有一个容量(capacity),如果容量不足,容器会自动增大底层数组的大小

        数组进行扩容时,会将老数组中的元素重新拷贝一份到新的数组中,每次数组容量的增长大约是其原容量的1.5倍。这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。或者根据实际需求,通过调用ensureCapacity方法来手动增加ArrayList实例的容量。

源代码的扩容方式:

Object[] elementData; // 存放元素的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间
private static final int DEFAULT_CAPACITY = 10; // 默认容量大小
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// 获取旧空间大小
int oldCapacity = elementData.length;
// 预计按照1.5倍方式扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 调用copyOf扩容
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
// 如果minCapacity小于0,抛出OutOfMemoryError异常
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

PS:Arrays.copyOf

// 扩容数组,将新长度设置为原长度的两倍 Integer[] expandedArray = Arrays.copyOf(originalArray, originalArray.length * 2);

缺点: 

        在ArrayList 任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后 搬移,时间复杂度为 O(n) ,效率比较低,因此 ArrayList 不适合做任意位置插入和删除比较多的场景

标签:顺序,int,ArrayList,elementData,list,add,minCapacity
From: https://blog.csdn.net/qq_66333706/article/details/141604197

相关文章

  • 数据结构:顺序表
    目录结构体顺序表存储数据类型结构体 顺序表结构体函数 初始化顺序表判断顺序表是否存满判断顺序表是否为空顺序表插入新元素在指定位置插入新元素遍历顺序表所有元素,对每个元素完成指定操作   (指定操作1) 打印所有元素    (指定操作2)更新指定元素......
  • 数据结构——顺序表
    数据结构顺序表基本概念顺序表:顺序存储的线性表。链式表:链式存储的线性表,简称链表。顺序存储就是将数据存储到一片连续的内存中,在C语言环境下,可以是具名的栈数组,或者是匿名的堆数组。存储方式不仅仅只是提供数据的存储空间,而是必须要能体现数据之间的逻辑关系。当采用......
  • firewalld:富规则的优先级顺序
    一,firewalld的rich规则执行逻辑如下: 1,日志规则2,drop/reject规则3,accept规则二,例子:验证是否先匹配reject规则1,添加两条规则:第一条允许指定ip访问22端口第二条禁止同一个ip访问[root@blog~]#firewall-cmd--add-rich-rule='rulefamily="ipv4"sourceaddress="13.17.12.21......
  • 基于顺序表实现通讯录功能项目
    本文通过顺序表实现通讯录的功能,增删查改数据首先实现顺序表的功能,再用顺序表实现通讯录的功能顺序表中的成员为一个结构体对象con,自定义的类型,里面包含着联系人的姓名性别年龄电话地址seqlist.h:顺序表头文件#pragmaonce#define_CRT_SECURE_NO_WARNINGS1#include<ass......
  • 在array.orderby C#上获得随机顺序
    原文链接:https://cloud.tencent.com/developer/information/%E5%A6%82%E4%BD%95%E5%9C%A8array.orderby%20C%23%E4%B8%8A%E8%8E%B7%E5%BE%97%E9%9A%8F%E6%9C%BA%E9%A1%BA%E5%BA%8F在C#中,要在数组(array)的OrderBy方法中获得随机顺序,可以使用Random类来生成一个随机数作为排序的依据......
  • 调用ArrayList的add方法抛异常UnsupportedOperationException
    调用ArrayList的add方法抛异常UnsupportedOperationException对于一些想要把数组转成List的需求,可能会使用到Arrays.asList()获取List对象,但是这里面也存在一些问题。示例代码如下voidtest1(){List<Object>list=Arrays.asList();list.add("hello");......
  • 【数据结构】二叉树的顺序结构,详细介绍堆以及堆的实现,堆排序
    目录1.二叉树的顺序结构2.堆的概念及结构3.堆的实现3.1堆的结构3.2堆的初始化3.3堆的插入 3.4堆的删除3.5获取堆顶数据3.6堆的判空3.7堆的数据个数3.8堆的销毁4.堆的应用4.1堆排序4.1.1向下调整建堆的时间复杂度 4.1.2向上调整建堆的时间复杂......
  • 【两栈共享空间】------一种特殊的顺序栈
    前言:虽然顺序栈的存储已经十分方便,但是它有一个非常致命的缺陷:即必须事先确定数组存储空间的大小,万一不够用就需要动态扩容但对于两个相同类型的栈,我们可以做到最大限度的利用其事先开辟的存储空间,既让两栈共享空间1.共享栈的定义两个栈共享同一个存储空间,这片空间不单......
  • ArrayList遍历, 元素查找
    1,ArrayList集合的遍历与数组类似,都可以使用foreach语句string[]str1={"a","b","c","d","e","f"};ArrayListList=newArrayList(str1);foreach(variteminList)......
  • ArrayList元素的删除(4种函数)
    1Clear()方法Clear()方法用来从ArrayList中移除所有元素,语法格式如下。string[]str1={"a","b","c"};ArrayListList=newArrayList(str1);List.Clear();2Remove()方法Remove()方法用来从ArrayList中移除特定对象的第一个......