I学霸官方免费教程三十:Java集合框架之List集合

集合框架

在数组的使用过程中可以看到,想要向数组中插入元素和删除元素非常麻烦,而且数组的长度是无法改变的。java为我们提供了批量存储数据更加方便的容器,就是集合。

集合和数组的作用一样,都是为了使用一个变量来存储一批数据的;但集合使用起来更加方便,而且集合的长度是可以变化的。

List接口

List集合可以存储有序的,可重复的数据;

常用的子类是ArrayList和LinkedList两个类

ArrayList类

这是一个底层由数组实现的集合类,是对数组进行了封装。

实例:
package collection.list.arrayList;
import java.util.ArrayList;
/**
 * ArrayListDemo类
 * 演示ArrayList类中常用方法的使用
 * @author 学霸联盟 - 赵灿
 */
public class ArrayListDemo {
	public static void main(String[] args) {
		//当创建ArrayList对象时,底层会创建一个空的Object类型的数组
		ArrayList arrayList = new ArrayList();
		//循环存入数据
		for (int element = 1; element <= 11; element++) {
			/*
			 * 通过arrayList的add方法向集合中添加数据
			 * 任何类型的数据都会被转换成Object类型加入集合
			 * 当加入集合的数据为基本数据类型的数据时
			 * 会先将基本数据类型的数据转换成对应的包装类类型
			 * 例如:int类型的数据会先转换成Integer类型
			 * 然后再将Integer类型转换成Object类型
			 * 从基本数据类型转换成包装类类型的过程叫做自动装箱
			 * 这个转换过程由系统自动处理完成
			 *
			 * 添加第一个数据时,底层会重新创建长度为10的Object类型的数组
			 * 这里的10一般认为是ArrayList集合的初始长度
			 * 并把第一个数据存储到底层Object类型数组下标为0的位置上;
			 * 当底层数组存满后,再向集合中添加元素时,
			 * 底层会创建一个长度为原数组长度1.5倍的新数组
			 * 这里的1.5叫做集合的增长因子
			 * 并将原数组中的所有元素复制到新数组中
			 * 然后在新数组下标为原数组长度的位置上新增当前元素
			 *
			 * 例如:本例中第一次增长在存入第11个元素时,即element==11时
			 * 此时原数组的长度为10(最大下标为9)
			 * 底层会新建长度为15(10的1.5倍)的Object类型的数组
			 * 然后将原数组中所有数据复制到新数组中
			 * 然后在新数组下标为10的位置上存入元素11
			 * 注意:这里的element不是集合的下标,而是存入集合的元素(数据)
			 * 理论最大存储元素个数为int类型的最大值2147483647 [0x7fffffff]
			 */
			arrayList.add(element);
		}
		/*
		 * 循环取出数据
		 * 这里的index代表集合的下标
		 * 集合的长度使用size方法获取,而不是length属性,也不是length方法
		 * 获取数组长度使用的length属性
		 * 获取String长度使用的是length方法
		 */
		for (int index = 0; index < arrayList.size(); index++) {
			// 使用get方法获取集合中的数据,获取出来的数据类型为Object
			Object element = arrayList.get(index);
			// 强制类型转换
			Integer data = (Integer)element;
			/*
			 * Integer是引用类型
			 * 那么问题来了,基本数据类型的变量e为什么可以赋引用类型的值呢?
			 * 因为Integer是int的包装类
			 * 从包装类型转换成基本数据类型的过程,叫做自动拆箱
			 * 这个转换过程也由系统自动处理完成
			 */
			int e = data;
			//每次循环均输出变量e的值和两个空格
			System.out.print(e + "  ");
		}
	}
}
运行结果:1  2  3  4  5  6  7  8  9  10  11 

小结:

1、集合的初始长度为10,增长因子为1.5

2、理论最大存储长度为int类型的最大值2147483647 [0x7fffffff]

3、存入基本数据类型数据时存在自动装箱

4、未使用泛型时,取出数据的数据类型是Object

5、获取集合长度使用size方法

6、通过结果可以看到,取出的顺序和存入的顺序是一致的,所以它是有序的集合

7、底层由数组实现,其内存空间是连续的,所以查询元素速度较快

8、插入和删除速度较慢,因为要将插入位置之后的元素依次后移,删除位置之后的元素依次前移

实例:演示ArrayList类中的常用方法的使用
package collection.list.arrayList;
import java.util.ArrayList;
import java.util.Arrays;
/**
 * ArrayListDemo类
 * 演示ArrayList类中常用方法的使用
 * @author 学霸联盟 - 赵灿
 */
public class ArrayListDemo2 {
	public static void main(String[] args) {
		//创建ArrayList对象
		ArrayList arrayList1 = new ArrayList();
		ArrayList arrayList2 = new ArrayList();
		//循环存入数据
		for (int element = 1; element <= 3; element++) {
			//循环结束后两个集合中都有1,2,3三个元素
			arrayList1.add(element);
			arrayList2.add(element);
		}
		//遍历集合;运行结果:1  2  3
		ergodicArrayList(arrayList1);
		/*
		 * 插入数据,向集合下标为1的位置,插入数据10
		 * 插入的下标值必须小于等于集合长度
		 * 即:插入下标<=集合.size();
		 * 如果插入下标大于集合长度的位置,会出现IndexOutOfBoundsException
		 */
		arrayList1.add(1,10);
		//遍历插入数据后的集合;运行结果:1  10  2  3
		ergodicArrayList(arrayList1);

		//依次向集合arrayList1中加入arrayList2集合中的每个元素
		arrayList1.addAll(arrayList2);
		//遍历插入数据后的集合;运行结果:1  10  2  3  1  2  3
		ergodicArrayList(arrayList1);

		//contains方法,判断集合中是否包含某个元素
		boolean isContains = arrayList1.contains(10);
		//输出结果:集合arrayList1是否包含10:true
		System.out.println("集合arrayList1是否包含10:" + isContains);
		//输出结果:集合arrayList1是否包含11:false
		System.out.println("集合arrayList1是否包含11:" + arrayList1.contains(11));

		//indexOf方法,获取某个元素在集合中左边开始第一次出现时的下标
		//输出结果:集合arrayList1中第一次出现2的下标为:2
		System.out.println("集合arrayList1中第一次出现2的下标为:" + arrayList1.indexOf(2));
		//lastIndexOf方法,获取某个元素在集合中最后一次(右边第一次)出现时的下标
		//输出结果:集合arrayList1中最后一次出现2的下标为:5
		System.out.println("集合arrayList1中最后一次出现2的下标为:" + arrayList1.lastIndexOf(2));

		//remove方法,删除对应下标的元素
		//如果传入的实参类型是byte、short、int和char类型时,根据下标移除
		arrayList1.remove(0);
		//运行结果:10  2  3  1  2  3
		ergodicArrayList(arrayList1);
		//移除arrayList1集合中的元素3,只会移除左边第一个匹配上的数据
		arrayList1.remove((Integer)3);
		//运行结果:10  2  1  2  3
		ergodicArrayList(arrayList1);

		//set方法,更新对应下标的元素
		arrayList1.set(3,1000);
		//运行结果:10  2  1  1000  3
		ergodicArrayList(arrayList1);

		//toArray方法,将集合转换成Object类型的数组
		Object[] array = arrayList1.toArray();
		//将数组转换成字符串形式
		String str = Arrays.toString(array);
		//运行结果:[10, 2, 1, 1000, 3]
		System.out.println(str);

		//清空集合中的所有元素
		arrayList1.clear();

		//isEmpty方法,判断集合是否为空,当且仅当size方法获得结果为0时,返回true
		//运行结果:集合arrayList1是否为空:true
		System.out.println("集合arrayList1是否为空:" + arrayList1.isEmpty());
}

	/**
	 * 遍历集合
	 */
	private static void ergodicArrayList(ArrayList arrayList){
		//循环取出元素
		for (int index = 0; index < arrayList.size(); index++) {
			// 使用get方法获取集合中的数据,获取出来的数据类型为Object
			Object element = arrayList.get(index);
			/*
			 * 当使用System.out.println()方法直接输出引用类型的对象时
			 * 输出的是对象.toString()方法的返回值
			 * 例如:
			 * System.out.println(element);和
			 * System.out.println(element.toString());是一样的
			 */
			System.out.print(element);
			//输出两个空格
			System.out.print("  ");
		}
		//换行
		System.out.print("\n");
	}
}
运行结果:
1  2  3
1  10  2  3
1  10  2  3  1  2  3
集合arrayList1是否包含10:true
集合arrayList1是否包含11:false
集合arrayList1中第一次出现2的下标为:2
集合arrayList1中最后一次出现2的下标为:5
10  2  3  1  2  3
10  2  1  2  3
10  2  1  1000  3
[10, 2, 1, 1000, 3]
集合arrayList1是否为空:true

另有Vector集合类,和ArrayList的区别:ArrayList是线程异步的(线程不安全的),Vector是线程同步的(线程安全的),因此导致Vector集合的性能非常低下,已基本不用,有兴趣的同学可以了解即可

既然ArrayList集合插入和删除效率较低,那么有没有比它更快的呢?

接下来看LinkedList集合类

LinkedList类

和ArrayList类基本相同,ArrayList有的方法LinkedList都有;但他们的实现方式不同,LinkedList采用双向链表的数据结构实现,当向集合中添加元素时,集合会创建一个节点Node,这个节点中会存储当前添加的元素,还会存储上一个节点和下一个节点,这样就形成了双向链表这一数据结构。而这样的结构修改和删除效率非常高效,但这个结构中节点与节点之间,在内存空间上是不连续的;所以查询效率要比ArrayList集合的查询效率低

实例:演示LinkedList部分特有方法
package collection.list.linkedList;
import java.util.LinkedList;
/**
 * LinkedListDemo类
 * 演示LinkedListDemo类中常用方法的使用
 * @author 学霸联盟 - 赵灿
 */
public class LinkedListDemo {
	public static void main(String[] args) {
		//创建LinkedList对象
		LinkedList linkedList = new LinkedList();
		for (int i = 0; i < 4; i++) {
			//循环向集合中添加数据
			linkedList.add(i+1);
		}
		//运行结果:1  2  3  4
		ergodicLinkedList(linkedList);

		//获取集合中第一个位置的元素
		Object first = linkedList.getFirst();
		//运行结果:集合中第一个元素为:1
		System.out.println("集合中第一个元素为:" + first);

		//获取集合中最后一个位置的元素
		Object last = linkedList.getLast();
		//运行结果:集合中最后一个元素为:4
		System.out.println("集合中最后一个元素为:" + last);

		//在集合的第一个位置插入元素
		linkedList.addFirst(0);
		//在集合的最后一个位置插入元素
		linkedList.addLast(6);

		//运行结果:0  1  2  3  4  6
		ergodicLinkedList(linkedList);

		//移除集合中第一个位置的元素
		linkedList.removeFirst();
		//移除集合中最后一个位置的元素
		linkedList.removeLast();

		//运行结果:1  2  3  4
		ergodicLinkedList(linkedList);
	}
	/**
	 * 遍历集合
	 */
	private static void ergodicLinkedList(LinkedList linkedList){
		//循环取出元素
		for (int index = 0; index < linkedList.size(); index++) {
			// 使用get方法获取集合中的数据,获取出来的数据类型为Object
			Object element = linkedList.get(index);
			/*
			 * 当使用System.out.println()方法直接输出引用类型的对象时
			 * 输出的是对象.toString()方法的返回值
			 * 例如:
			 * System.out.println(element);和
			 * System.out.println(element.toString());是一样的
			 */
			System.out.print(element);
			//输出两个空格
			System.out.print("  ");
		}
		//换行
		System.out.print("\n");
	}
}
运行结果:
1  2  3  4
集合中第一个元素为:1
集合中最后一个元素为:4
0  1  2  3  4  6
1  2  3  4  

总结:

以上我们提到的两种集合都是继承自List接口的,他们具有共同的特性,存入的值都是有顺序的,可以存入重复的值,可以使用下标访问元素

不同点

ArrayList:底层由数组实现,初始长度为10,增长因子1.5

缺点:插入和删除效率较低

优点:修改和查询效率较高

LinkedList:底层由双向链表实现,没有初始长度和增长因子

优点:插入和删除效率较高

缺点:查询和修改效率较低

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 05:49:55

I学霸官方免费教程三十:Java集合框架之List集合的相关文章

I学霸官方免费教程三十二:Java集合框架之Set集合

Set接口 Set集合是无序的.元素不可重复的结合常用集合类有HashSet和TreeSet HashSet类常用的两种List集合各有各的优点,那么有没有同时具备这两种List集合的优点的集合呢?答案是肯定的,就是Set集合. 实例: package collection.set.hashSet; import java.util.HashSet; import java.util.Iterator; /**  * 演示HashSet  * @author 学霸联盟 - 赵灿  */ publ

I学霸官方免费教程三十四:Java集合框架之泛型集合

泛型集合 泛型集合不是指某种集合,而是指在集合的基础上增加了泛型. 泛型集合中,一旦传入了泛型参数"类A":则只能向这个集合中添加类A或类A子类的对象,不能添加其他对象了. 从泛型集合中获取对象时,对象的类型是类A,而不是Object类型的对象了. 泛型List 例如:上面说到的两种List集合,都可以加入泛型 package collection.list.arrayList; import java.util.ArrayList; import java.util.List; /*

I学霸官方免费教程三十:Java基础教程之泛型

泛型 先给大家举个例子:如现在有一家工厂,可以生产手机,也可以生产电脑.以后还可能生产其他产品.如果给某个工厂加上了泛型,就规定了这个工厂只能生产手机或电脑,不能再生产其他产品了. 实例: package generic; /**  * 产品枚举Product  * @author 学霸联盟 - 赵灿  */ public enum Product { 手机,电脑 } package generic; /**  * 手机类Phone  * @author 学霸联盟 - 赵灿  */ public

I学霸官方免费教程三十五:Java集合框架之Collection接口和Collections类

Collection接口 Collection接口是List和Set接口的父接口,其中主要定义了一些集合基本操作的方法,包括与Iterator之间的关系List  extends  CollectionArrayList  implements  ListLinkedList  implements  ListVector  implements  ListSet  extends  CollectionHashSet  implements  SetSortedSet  extends  Se

I学霸官方免费教程三十九 :Java基础教程之线程

线程 线程和进程 进程:系统运行程序的最小单位:一个进程最少有一个线程线程:程序执行任务的最小单位:线程与线程之间并行一个进程至少有一个线程,在java中这个线程称为主线程,由系统创建,运行main方法.这样只有一个线程的程序也被称为单线程程序.主线程从程序入口main方法开始执行代码,执行任意方法中的代码都是按照自上而下的顺序执行的,如果只有一个主线程,又想实现在线听音乐这个功能的话,就很难实现.因为主线程必须先去下载音乐:下载完成后,在执行播放音乐:这显然不能满足当今人们对在线听音乐的需求.

I学霸官方免费教程三十六:Java数据结构之双向链表结构

数据结构之双向链表 例如:现有双向链表TwoWayLinked中存储着1,2,3,4四个元素,那么集合对象中会有4个节点A.B.C.D,由上述结构可以知道,节点A中存储着元素1和节点B:节点B中存储着元素2和节点A和节点C,节点C中存储着元素3和节点B和节点D,节点D中存储着元素4和节点C.如果现在要在元素2和3中间插入一个元素5: 过程如下: 1.创建节点E,E中存储元素5 2.将E中的上一个节点赋值为节点B 3.将B中的下一个节点修改为节点E 4.将E中的下一个节点赋值为节点C 5.将C中的

I学霸官方免费教程三十八 :Java基础教程之异常

异常 程序中不正常的情况分为两大类:错误(Error)和异常(Exception) 错误(Error):程序本身无法对这种不正常的情况进行处理,将会导致程序崩溃:例如:内存耗尽错误,JVM崩溃错误等异常(Exception):程序可以特殊的代码,对不正常的情况进行捕获和处理,程序可以继续运行:例如:除零异常,空指针异常,数组下标越界异常 捕获异常 语法格式1: try{  //可能出现异常的代码   }catch(异常类 变量名){ //出现异常后的处理代码 //printStackTrace(

I学霸官方免费教程三十一:Java集合框架之List集合

集合框架 在数组的使用过程中可以看到,想要向数组中插入元素和删除元素非常麻烦,而且数组的长度是无法改变的.java为我们提供了批量存储数据更加方便的容器,就是集合.集合和数组的作用一样,都是为了使用一个变量来存储一批数据的:但集合使用起来更加方便,而且集合的长度是可以变化的. List接口 List集合可以存储有序的,可重复的数据:常用的子类是ArrayList和LinkedList两个类 ArrayList类 这是一个底层由数组实现的集合类,是对数组进行了封装. 实例: package col

I学霸官方免费教程三十三:Java集合框架之Map集合

Map接口 Map集合采用键值对(key-value)的方式存储数据,其中键不可以重复.值可以重复. 常用类有HashMap.TreeMap和Properties HashMap类 假如,现在我有一个集合,集合中存储着一批WiFi的名称和密码,现在要求通过名称快速找到密码.这样的需求使用List集合实现起来非常困难,Java为我们提供了另一种形式的集合,可以很好的解决这样的问题.就是Map集合. 实例: package map.hashMap; import java.util.HashMap;