集合框架之List集合详解

前言

为什么使用集合?

数组的缺陷:定容[一旦数组定义好,数组的长度就无法改变],如果需要改变数组的长度,很复杂。

ArrayList数据结构也是数组那么为什么可以没有长度限制?

论证:ArrayList数据结构是数组

ini 复制代码
 public static void main(String[] args) throws Exception {
	        List list = new ArrayList();
	        for (int i = 0; i < 100; i++) {
	            System.out.print(i+"==");
	            list.add(i);
	            elementDataLength(list);
	        }

	    }
	 
	
 public static void elementDataLength(List list) throws Exception {
	        Field ed = list.getClass().getDeclaredField("elementData");
	        ed.setAccessible(true);
	        Object[] o = (Object[]) ed.get(list);
	        System.out.println("当前List集合容量为:"+o.length);
	    }

​编辑

结论:

ArrayList的默认长度是10,如果超出规定长度会增长1.5倍,并向下取整

例如 101.5=15、151.5=22、22*1.5=33 ...

如果想要优化那就规定一个较大的长度让ArrayList少做增长的事情

一.什么是UML?

UML是统一建模语言的简称,它是一种由一整套图表组成的标准化建模语言。UML用于帮助系统开发人员阐明,展示,构建和记录软件系统的产出。UML代表了一系列在大型而复杂系统建模中被证明是成功的做法,是开发面向对象软件和软件开发过程中非常重要的一部分。UML主要使用图形符号来表示软件项目的设计,使用UML可以帮助项目团队沟通、探索潜在的设计和验证软件的架构设计。

​编辑

二.集合框架

编辑

三.list集合

3.1.list集合特点

有序:List集合数据存储进去顺序和读取顺序一致。

不唯一:List集合数据允许添加重复的数据。

list是可以允许添加重复元素,那怎么变成不可重复?

首先我们要了解集合的底层原理,默认是比较内存地址,我们只需要重写equals,利用自己定制的一套规则判断是否重复,就可以过滤掉重复的元素。

3.2.遍历方式(for;foreach;迭代器)

for下标遍历

csharp 复制代码
List lst=new ArrayList();
lst.add("zs");
lst.add("ls");
lst.add("ww");
for (int i = 0; i < lst.size(); i++) {
	System.out.println(lst.get(i));
}

forreach遍历

csharp 复制代码
List lst=new ArrayList();
lst.add("zs");
lst.add("ls");
lst.add("ww");
for (String str : lst) {
	System.out.println(str);
}

迭代器

vbnet 复制代码
List lst=new ArrayList();
lst.add("zs");
lst.add("ls");
lst.add("ww");
Iterator iterator = lst.iterator();
while(iterator.hasNext()){
	System.out.println(iterator.next());
}

3.3.删除list集合内容(for正反向删除;迭代器删除)

for循环正向删除

ini 复制代码
List lst=new ArrayList<>();
lst.add(12);
lst.add(13);
lst.add(14);
lst.forEach(System.out::println);
System.out.println("删除之前集合大小:"+lst.size());
int size = lst.size();
for (int i = 0; i <size; i++) {
	lst.remove(0);
}
System.out.println("删除之后集合大小:"+lst.size());

⚠注意这里正向删除必须先把集合长度利用一个变量保存,否则每次删除之后数组长度会发生变化随之原数组下标也会发生变化,i++后从而删不干净,并且remove(0)的好处就是每次都会有下标为0的数组存在。

for遍历逆向删除

ini 复制代码
List lst=new ArrayList<>();
lst.add(12);
lst.add(13);
lst.add(14);
lst.forEach(System.out::println);
System.out.println("删除之前集合大小:"+lst.size());
int size = lst.size()-1;
for (int i = size; i >=0; i--) {
	lst.remove(i);
}
System.out.println("删除之后集合大小:"+lst.size());

⚠注意这里同样用变量接收但是长度需要减一,因为数组下标是从0开始的。

迭代器删除

scss 复制代码
List lst=new ArrayList<>();
lst.add(12);
lst.add(13);
lst.add(14);
lst.forEach(System.out::println);
System.out.println("删除之前集合大小:"+lst.size());
Iterator<String> iterator = lst.iterator();
//判断下一个元素是否存在
while(iterator.hasNext()) {
    //若存在,移动到下一个元素位置
    //易出错
    iterator.next();
    //删除元素
    iterator.remove();
}
System.out.println("删除之后集合大小:"+lst.size());

✳️迭代器中的hasNext()与next()区别:

next是移动到下一个元素位置;

hasNext是判断下一个元素是否存在,返回值是true和false;

如果while()里面写的是next,会报数组下标越界,所有先判断有无下一个属性在进行移动并删除。

迭代器原理

编辑

四.泛型介绍

4.1什么是泛型?泛型的作用?

JDK1.5以上的新特性

以类型为参数的类叫做泛型

泛型的默认类型是Object

作用是提高程序的规范性和简化代码

五.拆装箱概念

✳️装箱就是将值类型变成引用类型,而拆箱就是将引用类型变为值类型,基本类型一共有八个分别是

整数类型:long、int、short、byte;

浮点类型:float、double;

字符串类型:char;

布尔类型:boolean;

⚠注意:String是引用类型;

装箱:值类型到引用类型

ini 复制代码
int a=10;
Integer b=new Integer(a);

拆箱 :引用类型到值类型

ini 复制代码
Integer c=new Integer(10);
int d=c.intValue();

六.ArrayList、LinkedList和Vector的区别

6.1.ArrayList和LinkedList的区别

相同点

1、LinkedeList和ArrayList都实现了List接口。

2、ArrayList和LinkedList是两个集合类,用于存储一系列的对象引用(references)。

不同点

1、ArrayList底层实现是数组,而LinkedList是双向链表。

2、ArrayList查询修改快(下标)、增删慢、LinkedList是查询修改慢,但是在插入删除时效率比较高。

原因

因为ArrsyList是数组,而LinkedList是双向链表​编辑

ArrayList 内部采用数组作为其存储结构,当查询其元素时,它可以通过索引直接访问数组中的元素,因此查询速度很快,时间复杂度为 O(1)。但是,在进行插入、删除等操作时需要对数组进行移动,这个过程比较耗时,因此在大量插入、删除操作的场景下,性能较差,时间复杂度可能为 O(n)。

LinkedList 内部采用链表作为其存储结构,它的插入、删除等操作比较快,时间复杂度为 O(1),因为只需要在链表中插入或删除一个结点即可。但是,在查询元素时需要遍历整个链表,因此查询速度比较慢,时间复杂度为 O(n)。

总的来说,如果我们需要进行大量的查询操作而仅少量的插入、删除操作,那么使用 ArrayList 应该更合适;如果我们需要进行大量的插入、删除操作而仅少量的查询操作,那么使用 LinkedList 应该更合适。

6.2.ArrayList和Vector的区别

相同点

1、ArrayList和Vector都是用数组实现的

2、默认初始化大小都是10

不同点

1、Vector多线程是安全的,而ArrayList不是。Vector类中的方法很多有synchronized进行修饰,这样就导致了Vector在效率上无法与ArrayList相比;

2、两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同的。(ArrayList每次存储时会检查空间大小,不够时会扩充为原来的1.5倍,Vector会扩充为原来空间的2倍)

七. 面试题---利用LinkedList完成堆栈

解析:这个问题考验的是我们是否了解堆栈的特点以及对LinkedList的方法熟练度。

首先堆栈的特点就是"先进后出",也就是先加进去的元素最后出来。LinkedList中刚好有三个方法,一个是拿到第一个元素(栈顶元素)getFirst()和删除第一个元素removeFirst(),和addFirst()添加到第一个元素下标为0(不从末尾追加元素)利用这三个方法,我们就可以完成LinkedList模拟堆栈。​编辑

csharp 复制代码
public class Test02 {
	//首先堆栈的特点就是先进后出,就像是"弹夹"
	//所以我们将这一系列操作称之为装弹和开枪

	private LinkedList  lkl=new LinkedList<>();
	
	/**
	 * 装弹
	 */
	public void add(Object obj) {
		lkl.addFirst(obj);
	}
	
	/**
	 * 开枪
	 * @return
	 */
	public Object remove() {
		//获取栈顶
		Object first = lkl.getFirst();
		//删除栈顶
		lkl.removeFirst();
		return first;
	}
	
	/**
	 * 记录子弹有多少颗
	 * @return
	 */
	public int size() {
		return lkl.size();
	}
	
	//模拟装弹和开枪
	public static  void main(String[] args) {
		Test02 d=new Test02();
		//装弹 顺序 1 2 3 
		d.add("1");
		d.add("2");
		d.add("3");

        //注意:这里虽然添加的顺序是1 2 3,但是调用了addFirst()
        //顺序其实是3 2 1

		//开枪 顺序 3 2 1
		while(d.size()!=0) {
			System.out.println(d.remove());
		}
		
		
	}
}

看到这里很不容易,为博主留下一个微不足道的赞吧!!😘

相关推荐
Monodye3 分钟前
【Java】网络编程:TCP_IP协议详解(IP协议数据报文及如何解决IPv4不够的状况)
java·网络·数据结构·算法·系统架构
一丝晨光9 分钟前
逻辑运算符
java·c++·python·kotlin·c#·c·逻辑运算符
无名指的等待71233 分钟前
SpringBoot中使用ElasticSearch
java·spring boot·后端
Tatakai251 小时前
Mybatis Plus分页查询返回total为0问题
java·spring·bug·mybatis
武子康1 小时前
大数据-133 - ClickHouse 基础概述 全面了解
java·大数据·分布式·clickhouse·flink·spark
.生产的驴1 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
Code哈哈笑1 小时前
【C++ 学习】多态的基础和原理(10)
java·c++·学习
chushiyunen1 小时前
redisController工具类
java
A_cot2 小时前
Redis 的三个并发问题及解决方案(面试题)
java·开发语言·数据库·redis·mybatis
AskHarries2 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端