zoukankan      html  css  js  c++  java
  • 7.4 List集合


    List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。

    一、改进的List接口和ListIterator接口

    1、List集合的增、删、替换、插入、截取等基本操作

    List是Collection接口的子接口,继承了Collection接口中的所有方法,且List增加了一些根据索引来操作集合元素的方法:
    ★void add(int index,Object element):将元素element插入到List集合的index处
    ★boolean addAll(int index ,Collection c):将集合c所包含的所有元素全部插入到List集合的索引index处
    ★Object get(int index):返回集合index索引处的元素
    ★int indexOf(Object o):返回对象o在List集合对象中第一次出现的位置索引
    ★int lastIndexOf(Object o):返回对象o在List集合对象中最后一次出现的位置索引
    ★Object remove(int index):删除并返回index索引处的元素
    ★Object set(int index, Object element):将index索引处的元素替换为element对象,返回被替代的旧元素
    ★List subList(int fromIndex,int toIndex):返回索引fromIndex到toIndex(不包含)处所有集合元素组成的子集合
    所有List实现类都可以调用这些方法来操作集合元素,与set集合相比,List增加了根据根据索引来插入、替换和删除集合元素的方法。
    List的常规用法:

    import java.util.ArrayList;
    public class ListTest 
    {
    	public static void main(String[] args) 
    	{
    		var books=new ArrayList();
    		//向books集合中添加三个元素
    		books.add("轻量级Java EE企业级应用实战");
    		books.add("疯狂Java讲义");
    		books.add("疯狂Android讲义");
    		//将新字符串插入到第二个位置
    		books.add(1,"疯狂Ajax讲义");
    		for(int i=0;i<books.size();i++)
    		{
    			System.out.println(books.get(i));
    		}
    		//删除第三个元素
    		books.remove(2);
    		System.out.println(books);
    
    		//判断指定元素在List集合中得位置:输出1表示第二位
    		System.out.println(books.indexOf(new String("疯狂Ajax讲义")));//①
    		//将第二个元素替换成新的字符串
    		books.set(1,"疯狂Java讲义");
    		System.out.println(books);
    		//第二个元素到第三个元素(不包括)截取成子集和
    		System.out.println(books.subList(1,2));
    	}
    }
    
    ---------- 运行Java捕获输出窗 ----------
    轻量级Java EE企业级应用实战
    疯狂Ajax讲义
    疯狂Java讲义
    疯狂Android讲义
    [轻量级Java EE企业级应用实战, 疯狂Ajax讲义, 疯狂Android讲义]
    1
    [轻量级Java EE企业级应用实战, 疯狂Java讲义, 疯狂Android讲义]
    [疯狂Java讲义]
    
    输出完成 (耗时 0 秒) - 正常终止
    

    List判断两个对象是否相等只要通过equals()方法比较返回true即可。①代码处是两个不同的对象,具有不同的hashCode值,但是,Java仍然认为它们相等,因此可以返回其索引值。下面举例说明:

    import java.util.ArrayList;
    class  A 
    {
    	public boolean equals(Object obj)
    	{
    		return true;
    	}
    }
    public class ListTest2
    {
    	public static void main(String[] args)
    	{
    		var books=new ArrayList();
    		books.add("轻量级Java EE企业级应用实战");
    		books.add("疯狂Java讲义");
    		books.add("疯狂Android讲义");
    		System.out.println(books);
    		//删除集合中的A对象,将导致第一个元素被删除
    		books.remove(new A());//1
    		System.out.println(books);
    		//删除集合中的A对象,再次导致第一个元素被删除
    		books.remove(new A());//2
    		System.out.println(books);
    
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    [轻量级Java EE企业级应用实战, 疯狂Java讲义, 疯狂Android讲义]
    [疯狂Java讲义, 疯狂Android讲义]
    [疯狂Android讲义]
    
    输出完成 (耗时 0 秒) - 正常终止
    

    在代码1处执行Collection接口中的remove()方法试图删除一个A对象,List将会调用该对象A的equals()方法依次与与集合中的元素进行比较,如果该equals()方法以某个集合作为参数时返回true,List集合将会删除该元素——A类重写了equals()方法,总是返回true。所以在比较集合中的第一个元素时,就会删除第一个元素。

    2、Java 8还为List接口增加了两个默认方法——replaceAll()和sort()方法

    ★void replaceAll(UnaryOperator operator):根据operator指定计算规则重新设置List集合的所有元素。
    ★void sort(Comparator c):根据Comparator 参数对List集合的元素排序
    程序实例:

    import java.util.ArrayList;
    public class ListTest3 
    {
    	public static void main(String[] args) 
    	{
    		var books=new ArrayList();
    		books.add("轻量级Java EE企业级应用实战");
    		books.add("疯狂Java讲义");
    		books.add("疯狂Android讲义");
    		books.add("疯狂ios讲义");
    
    		//使用目标类型为Comparator的Lambda表达式对List集合排序
    		books.sort((o1,o2)->((String) o1).length()>((String) o2).length()?1:((String) o1).length()==((String) o2).length()?0:-1);//1
    		System.out.println(books);
    
    		//使用目标类型为UnaryOperator的Lambda表达式来替换集合中的所有元素
    		books.replaceAll(ele->((String) ele).length());//2
    		System.out.println(books);
    	}
    }
    ---------- 运行Java捕获输出窗 ----------
    [疯狂ios讲义, 疯狂Java讲义, 疯狂Android讲义, 轻量级Java EE企业级应用实战]
    [7, 8, 11, 17]
    
    输出完成 (耗时 0 秒) - 正常终止
    

    代码1处,传给sort()方法lambda表达式指定排序规则:字符串越长越大。因此执行完这段代码,List集合的字符串将会按照从短到长顺序排序。
    代码2处,传给replaceAll()方法lambda表达式指定替换集合元素的规则:直接用集合元素的长度作为新元素。

    3、Iterator接口和改进的ListIrerator接口

    List除了继承了Iterator接口中的iterator()方法,返回一个迭代对象。List还提供了一个额外的listIterator(0方法,该方法返回一个ListIterator对象,ListIterator接口继承Iterator接口,提供了专门操作List的方法。ListIterator在Iterator接口基础上增加了以下方法:
    ★boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。
    ★Object previous():返回该迭代器的上一个元素
    ★void add(Object o):在指定位置插入一个元素。
    ListIterator与普通的Iterator相比,ListIterator增加了向前迭代的功能(Iterator只能向后迭代),而且ListIterator还可以通过add()方法向List集合中添加元素(Iterator只能删除元素)

    import java.util.ArrayList;
    public class ListIteratorTest  
    {
    	public static void main(String[] args) 
    	{
    		ArrayList books=new ArrayList();
    		books.add("西游记");
    		books.add("三国演义");
    		books.add("水浒传");
    		books.add("红楼梦");
    		var it=books.iterator();
    		//Iterator只能向后迭代和删除功能
    		while(it.hasNext())
    		{	
    			var ele=it.next();
    			if(ele=="红楼梦")
    			{
    				it.remove();
    			}
    			else
    				System.out.println(ele);
    		}
    		System.out.println(books);//[西游记, 三国演义, 水浒传]
    	
    		//ListIterator接口向后访问和增加功能
    		var lit=books.listIterator();
    		while(lit.hasNext())
    		{
    			var ele=lit.next();
    			if(ele=="水浒传")
    			{
    				lit.add("红楼梦");	
    			}
    			System.out.println(ele);
    		}
    		System.out.println(books);//[西游记, 三国演义, 水浒传, 红楼梦]
    		//ListIterator接口的向前访问
    		while(lit.hasPrevious())
    		{
    			System.out.println(lit.previous());
    		}
    	}
    }
    西游记
    三国演义
    水浒传
    [西游记, 三国演义, 水浒传]
    西游记
    三国演义
    水浒传
    [西游记, 三国演义, 水浒传, 红楼梦]
    红楼梦
    水浒传
    三国演义
    西游记
    请按任意键继续. . .
    

    二、 ArrayList和Vector实现类

    ArrayList和Vector作为List类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的、允许再分配的Object[]数组。ArrayList和Vector对象使用initialCapacity参数来设置该数组的长度,当向ArrayList和Vector集合中添加元素超过了数组的长度时,它们initialCapacity会自动增加。
    在多数编程情况下,程序员可以不用去管initialCapacity。但如果向ArrayList和Vector集合中添加大量的元素时,可使用ensureCapacity(int minCapacity)方法一次性地增加initalCapacity。可以减少重分配的次数,从而提高性能。
    如果没有指定initialCapacity参数,则Object[]数组的长度默认为10.
    ArrayList和Vector提供了两个方法来重现分配Object[]数组:
    ★void ensureCapacity(int minCapacity):将ArrayList或Vector集合的Object[] 数组长度增加大于或等于minCapacity.
    ★void trimToSize():调整ArrayList或Vector集合的Object[] 数组长度为当前元素的个数。调用该方法可减少ArrayList和Vector集合对象所占的存储空间。

    import java.util.ArrayList;
    public class ArrayListTest1 
    {
    	public static void main(String[] args) 
    	{
    		//创建空的ArrayList集合时不指定initialCapacity参数,Object[]数组默认长度为10
    		var al=new ArrayList();
    		al.add(0,"good");
    		al.add(1,"morning");
    		System.out.println(al.size());//2
    		//将集合转换为数组
    		Object[] array=al.toArray();
    		System.out.println(array.length);//2
    
    		//指定数组的长度
    		var al1=new ArrayList();
    		al1.ensureCapacity(4);
    		System.out.println(al1.size());//0
    		al1.add('a');
    		al1.add('b');
    		al1.add('c');
    		al1.add('d');
    		al1.add('e');
    		System.out.println(al1.size());//5
    	}
    }
    

    两者的区别:
    1、Vector类是古老的集合,那时设计不完美,有一些方法名很长的方法,而Vector系列中方法名更短的方法属于后来新增的方法。ArrayList开始作为List的主要实现类,没有那些方法名很长的方法。实际上Vector有很多缺点,应该减少使用Vector。
    2、ArrayList的线程是不安全的,当多个线程同时访问同一个ArrayList集合时,如果由超过一个以上的线程修改了ArrayList,则程序必须手动保证该集合的同步性;但Vector集合的线程是安全的,无需保证该集合的同步性。但是因此Vector的性能要低于ArrayList。我们仍然不推荐使用Vector。我们通常使用一个Collection的工具类,它可以将一个ArrayList线程变得安全。
    3、Vector还提供一个子类Stack,用于模拟“栈”这种数据结构,“栈”通常是指后进先出(LIFO)的容器。最后push进栈的元素,最先被pop出栈。注意进栈和出战都是Object,因此从栈取出元素必须进行类型转换,除非只是使用Object具有的操作。
    Stack类提供的方法:
    ★Object peek():返回栈的第一个元素,但并不把该元素"pop"出栈
    ★Object pop():返回栈的第一个元素,并将该元素pop出栈
    ★void push(Object item):将一个元素push进栈,最后一个进栈的元素总是位于栈顶。
    注:由于Stack是继承Vector的,因此它的线程是安全的、性能较差的。需要使用栈这种数据结构,建议使用ArrayDeque代替它。

    import java.util.Stack;
    public class StackTest 
    {
    	public static void main(String[] args) 
    	{
    		var st=new Stack();
    		st.add("a");
    		st.add("b");
    		st.push("c");
    		st.add("d");
    		//返回栈的第一个元素,不pop出栈
    		System.out.println(st.peek());//d
    		System.out.println(st);//[a, b, c, d]
    		////返回栈的第一个元素,pop出栈
    		System.out.println(st.pop());//d
    		System.out.println(st.pop());//c
    		System.out.println(st);//[a, b]
    	}
    }
    

    三、固定长度的List

    操作数组的工具类Arrays,该工具类提供了一个asList(Object... a)方法,该方法可以把一个数组或指定个数的对象转换为一个List集合,这个List集合既不是ArrayList的实例,也不是Vector实现类的实例,而是Arrays内部类的ArrayList的实例。
    Arrays.ArrayList是一个固定长度的List集合,程序只能遍历该集合的元素,不可增加、删除该集合中的元素。

    import java.util.Arrays;
    public class FixedSizeList 
    {
    	public static void main(String[] args) 
    	{
    		String[] str={"疯狂Java讲义","轻量级Java EE企业应用实战"};
    		var fixedList=Arrays.asList(str);
    		//获取fixedList的实现类
    		System.out.println(fixedList.getClass());//class java.util.Arrays$ArrayList
    		//遍历集合中的元素
    		fixedList.forEach(obj->System.out.println("集合元素:"+obj));
    		//遍历集合元素方法2
    		var it=fixedList.iterator();
    		while(it.hasNext())
    		{
    			System.out.println(it.next());
    		}
    		//试图增加、删除元素将会引发异常Exception in thread "main" java.lang.UnsupportedOperationException
    		//fixedList.add(2,"疯狂Android讲义");
    		//fixedList.remove("疯狂Java讲义");
    
    		//执行替换
    		fixedList.set(1,"疯狂Android讲义");
    		System.out.println(fixedList);//[疯狂Java讲义, 疯狂Android讲义]
    
    	}
    }
    
  • 相关阅读:
    数据库自动备份
    VC查找文件特定位置的记录方法
    MFC利用ADO连接ACCESS数据库及其操作数据库的方法
    VC利用ODBC连接MySql数据库的方法及其操作数据的方法
    uwsgi和nginx的故事
    A JavaScript Image Gallery
    The DOM in JavaScript
    A brief look at the Objects in JavaScript
    3 ways of including JavaScript in HTML
    #3 working with data stored in files && securing your application (PART II)
  • 原文地址:https://www.cnblogs.com/weststar/p/12571346.html
Copyright © 2011-2022 走看看