学习笔记之JavaSE(30)--JavaAPI详解5

今天学习的内容是集合类之List接口


Collection接口有两个子接口:List接口与Set接口。List接口的实现类统称为List集合(列表),而Set接口的实现类统称为Set集合()。在实际开发中,要根据不同集合的特点,选择到底使用哪种集合:

  • 列表的特点:元素允许重复;有序,元素的顺序就是添加的顺序
  • 集的特点:元素不能重复;元素可能是无序的
实际上,集也可以是有序的(LinkedHashSet与TreeSet),所以在开发中选择列表或集的依据只有一个:是否需要重复元素!

List接口在Collection接口的基础上添加了许多特有方法,使得可以在列表的任意位置对元素进行增删改查(原因是列表建立了数组索引与对象的关联,而集却没有),常用方法如下:
  • add(int index, E e) 在列表的指定位置插入指定元素
  • addAll(int index, Collection<? extends E> c) 在列表的指定位置插入指定集合的所有元素
  • remove(int index) 删除指定位置的元素,并返回该元素
  • indexOf(Object o) 返回列表第一次出现指定元素的索引,如果列表不包含此元素,则返回 -1
  • lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1
  • get(int index) 返回列表中指定位置的元素
  • set(int index, E e) 用指定元素替换列表中指定位置的元素
  • subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分列表
  • listIterator() 获取列表迭代器对象(只能用于列表,可以进行反向迭代,也可以在迭代过程中改变列表)
使用上述方法的示例程序:
public class Test52 {

	public static void main(String[] args){
		
		List<String> list = new ArrayList<String>();
		show_1(list);
		show_2(list);
	}

	public static void show_2(List<String> list) {
		
		//获取列表所有元素的方法:使用迭代器或者get(index)方法
//		Iterator<String> it = list.iterator();
//		while(it.hasNext()){
//			System.out.println("迭代器方法:"+it.next());
//		}
		for (int i = 0; i < list.size(); i++) {
			System.out.println("get()方法:"+list.get(i));
		}
		
		//在迭代过程中改变列表,要使用列表迭代器(只有列表具备该功能)
		ListIterator<String> lit = list.listIterator();
		while(lit.hasNext()){//列表迭代器还可以反向迭代
			String str = lit.next();
			if(str.equals("kkk")){
				//!list.add("incredible!!");//在迭代过程中改变了列表,会发生ConcurrentModificationException
				lit.set("kkk incredible!!");
			}else if(str.equals("ab")){
				lit.add("yes");
			}
		}
		System.out.println(list);//[ab, yes, kkk incredible!!, 2, 3, ab, yes, cd, ef]
	}

	public static void show_1(List<String> list) {
		
		//列表允许添加重复元素
		list.add("ab");
		list.add("ab");
		list.add("cd");
		list.add("ef");
		System.out.println("列表:" + list + " 列表长度:" + list.size());//列表:[ab, ab, cd, ef] 列表长度:4
		
		//插入元素
		list.add(1,"kk");
		System.out.println("列表:" + list + " 列表长度:" + list.size());//列表:[ab, kk, ab, cd, ef] 列表长度:5
		List<String> l = new ArrayList<String>();
		l.add("1");
		l.add("2");
		l.add("3");
		list.addAll(2, l);
		System.out.println("列表:" + list + " 列表长度:" + list.size());//列表:[ab, kk, 1, 2, 3, ab, cd, ef] 列表长度:8
		
		//删除元素
		list.remove(2);
		System.out.println("列表:" + list + " 列表长度:" + list.size());//列表:[ab, kk, 2, 3, ab, cd, ef] 列表长度:7
		
		//获取指定元素的下标
		int a = list.indexOf("ab");
		int b = list.lastIndexOf("ab");
		System.out.println("a="+a+",b="+b);//a=0,b=4
		
		//根据下标获取元素
		String str = list.get(1);
		System.out.println("列表中下标为1的元素为:"+str);//列表中下标为1的元素为:kk
		
		//更改指定位置的元素
		list.set(1, "kkk");
		System.out.println("列表:" + list + " 列表长度:" + list.size());//列表:[ab, kkk, 2, 3, ab, cd, ef] 列表长度:7
		
		//获取子列表
		List<String> subList = list.subList(0, 3);
		System.out.println("子列表:" + subList + " 子列表长度:" + subList.size());//子列表:[ab, kkk, 2] 子列表长度:3
	}
}

常用的列表包括Vector、ArrayList和LinkedList,大概介绍一下它们的区别:
1.Vector:底层数据结构是数组,实现了可变数组,是同步
   缺点:向列表中间插入、删除元素和随机访问列表中元素的速度都较慢
2.ArrayList:底层数据结构是数组,实现了可变数组,是不同步的,替代了Vector
   缺点:向列表中间插入、删除元素的速度较慢(牵一发动全身)
   优点:随机访问列表中元素的速度较快(数组在内存中是连续的)
3.LinkedList:底层数据结构是链表,是不同步
   缺点:随机访问列表中元素的速度较慢(链表在内存中是不连续的)
   优点:向列表中间插入、删除元素的速度较快(修改对象中存储的内存地址即可)

总结:如果要向列表中间频繁地插入和删除元素,建议使用LinkedList;如果要进行大量的随机访问,就使用ArrayList;程序中不应该使用过时的Vector

面试题:
1.什么是迭代器Iterator?
答:Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的
迭代方法。迭代器可以在迭代的过程中删除底层集合的元素,但是不可以直接调用集合的
remove(Object Obj)删除,可以通过迭代器的 remove()方法删除。
2.Iterator和ListIterator的区别是什么?
答:Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。
3.阐述ArrayList、Vector、LinkedList的存储性能和特性。
答:ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。但是由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象来增强实现)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值