数组ArrayList、LinkedList,集合

本文探讨了Java中的ArrayList和LinkedList两种数据结构,分析了它们在存储、查找、插入和删除操作上的时间复杂度和空间复杂度。ArrayList适合随机访问,但插入和删除效率较低,而LinkedList在插入和删除上具有优势,但查找效率不高。此外,还介绍了Java集合框架的优势,如动态扩容、类型安全和灵活性,并提到了Iterator迭代器作为遍历集合的工具。最后,讨论了数组与集合的区别,强调了集合在面向对象编程中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList

存储区间是连续的,占用内存严重,故空间复杂度很大。但数组的二分查找(前提是必须有序)

时间复杂度小,为O(logN);
数组的特点是:

        - 寻址容易(arr[n]=arr[0]+n*每个元素的长度,时间复杂度为O(1))
        - 插入和删除困难(可能会引发一半以上的数据元素移动,时间复杂度为O(n));
        - Java中的数组是定长的,如果需要变长则需要自行编程实现

import java.util.Arrays;
public class ArrayList {
	private Object[] data;//真正存储数据
	private int size=0;//记录存储的数据个数
	public ArrayList() {
		this(10);
	}
	
	public ArrayList(int len) {
		data=new Object[len];
	}
	
	public void add(Object obj) {
		data[size++]=obj;
		if(size>=data.length)
			resize();//扩容处理
	}

	private void resize() {
		System.out.println(size);
		Object[] res=new Object[data.length*3/2];
		System.arraycopy(data, 0, res, 0, size);
		this.data=res;
	}
	
	public void delete(int position) {
		if(position<0||position>=size)
			throw new ArrayIndexOutOfBoundsException();
		System.arraycopy(data, position+1, data, position, size-position-1);
		data[--size]=null;
	}
	
	public void update(int position,Object obj) {
		if(position<0||position>=size)
			throw new ArrayIndexOutOfBoundsException();
		data[position]=obj;
	}
	
	public void insert(int position,Object obj) {
		if(position<0||position>=size)
			throw new ArrayIndexOutOfBoundsException();
		System.arraycopy(data, position, data, position+1, size-position);
		data[position]=obj;
		size++;
		if(size>=data.length)
			resize();//扩容处理
	}
	
	public static void main(String[] args) {
		ArrayList list=new ArrayList(5);
		list.add(0);
//		for(int i=0;i<10;i++) {
//			list.add(i);
//		}
//		list.data[0]=10;
		for(int i=1;i<10;i++) {
			list.insert(0, i);
		}
		System.out.println(Arrays.toString(list.data));
		//容器为15,浪费了6个存储空间
//		list.delete(3);
//		System.out.println(Arrays.toString(list.data));
//		list.update(0, 99);
//		System.out.println(Arrays.toString(list.data));
		
	}
}

LinkedList

存储区间离散(数据不是连续存放的),占用内存比较宽松,故空间复杂度很小,但是时间复杂度很大O(N)。
链表的特点是:
        -寻址困难(可能需要通过遍历的方式查找元素,时间复杂度为O(n))
        -插入和删除容易(不需要引发元素的移动,仅仅只是进行地址的拷贝,时间复杂度为O(1))。

public class LinkedList {  //单向链表,实现不够完善,重点是原理
	
	private Node header;//头指针,指向链表中的第一个元素
	
	public void add(Object obj) {
		if(header==null) {
			header=new Node(obj);
		}else {
			Node p=header;
			for(;p.next!=null;p=p.next) ;
			p.next=new Node(obj);
		}
	}
	//增加和实际长度无关,但是为了查询到对应的位置,时间复杂度还是O(n)
	public void insert(int pos,Object obj) {
		Node p=header;
		for(int i=1;i<=pos;i++) {
			p=p.next;
		}
		Node tmp=new Node(obj);
		tmp.next=p.next;
		p.next=tmp;
	}
	//功能并不完善
	//删除和实际长度无关,O(1);但是实际上为了查询到对应的位置,时间复杂度还是O(n)
	public void delete(int pos) {
		Node p=header;
		for(int i=1;i<pos;i++) {
			p=p.next;
		}
		p.next=p.next.next;
	}
	
	public void show() {
		Node p=header;
		for(;p!=null;p=p.next)
			System.out.print(p.data+"\t");
	}
	
	public static void main(String[] args) {
		LinkedList ll=new LinkedList();
//		for(int i=0;i<10;i++) {
//			ll.add(i);
//		}
		ll.add(99);
		for(int i=0;i<10;i++) {
			ll.insert(0, i);
		}
		ll.show();
		ll.delete(3);
		System.out.println();
		ll.show();
	}
	
	class Node{
		private Object data;//存储的数据
		private Node next;//指向下一个Node对象的指针
		
		public Node(Object data) {
			this.data=data;
		}
	}
}

集合

Java集合类存放于 java.util 包中,是一个用来存放对象的容器
        - 集合只能存放对象。比如存一个int型数据1放入集合中,其实它是自动转换成Integer 类后存入的(装箱操作),Java中每一种基本类型都有对应的引用类型
        - 集合存放的是多个对象的引用,对象本身还是放在堆内存中
        - 集合可以存放不同类型,不限数量的数据类型。定义集合变量时如果不指定数据类型,则默认数据类型为Object

数组和集合的比较

针对Java中的数组定长,Java提出了集合框架,实现了一种变长存储数据的容器---集合

数组不是面向对象的,存在明显的缺陷,集合弥补了数组的缺点,比数组更灵活更实用,而且不同的集合框架类可适用不同场合。如下:
        - 数组能存放基本数据类型和对象,而集合类存放的都是对象的引用,而非对象本身
        - 数组容量固定无法动态改变,集合类容量动态改变
        - 数组无法判断其中实际存有多少元素,length只告诉了数组的容量,而集合的size()可以确切知道元素的个数
        - 集合有多种实现方式和不同适用场合,不像数组仅采用顺序表方式
        - 集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性即可实现各种复杂操作,大大提高了软件的开发效率

Iterator迭代器

Iterator迭代器:走访器,可以理解为集合中元素的指针
        它是Java集合的顶层接口(不包括map系列的集合,Map接口是map系列集合的顶层接口) 
 public interface Iterator<E> {
         boolean hasNext();  判断是否有后续元素
         E next(); 指针向后移动,同时返回指向的数据
         default void remove() {  删除指针所指向的元素
                 throw new UnsupportedOperationException("remove");
         }

 //使用lambda表达式的方式遍历所有元素
 default void forEachRemaining(Consumer<? super E> action) {
         Objects.requireNonNull(action);
         while (hasNext())
                 action.accept(next());
         }
 Iterable接口用以表示实现类是可以迭代的
 Iterator<T> iterator();

import java.util.ArrayList;
import java.util.Iterator;

public class Test1 {
	public static void main(String[] args) {
		ArrayList al=new ArrayList();
		for(int i=0;i<100;i++)
			al.add(i);
		//迭代访问集合中的每个元素
		Iterator it=al.iterator();
//		while(it.hasNext()) {
//			Object tmp=it.next();
//			System.out.println(tmp);
//		}
		it.forEachRemaining(System.out::println);
		System.out.println();
		al.forEach(System.out::println);//底层就是迭代访问
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值