List接口和ArrayList类

来自CloudWiki
跳转至: 导航搜索

数组和List

没有比较就没有伤害

在集合类中,List是最基础的一种集合:它是一种有序链表。

List的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,List的索引和数组一样,从0开始。

数组和List类似,也是有序结构,如果我们使用数组,在添加和删除元素的时候,会非常不方便。例如,从一个已有的数组{'A', 'B', 'C', 'D', 'E'}中删除索引为2的元素:

┌───┬───┬───┬───┬───┬───┐
│ A │ B │ C │ D │ E │   │
└───┴───┴───┴───┴───┴───┘
              │   │
          ┌───┘   │
          │   ┌───┘
          │   │
          ▼   ▼
┌───┬───┬───┬───┬───┬───┐
│ A │ B │ D │ E │   │   │
└───┴───┴───┴───┴───┴───┘

这个“删除”操作实际上是把'C'后面的元素依次往前挪一个位置,而“添加”操作实际上是把指定位置以后的元素都依次向后挪一个位置,腾出来的位置给新加的元素。这两种操作,用数组实现非常麻烦。


因此,在实际应用中,需要增删元素的有序列表,我们使用最多的是ArrayList。实际上,ArrayList在内部使用了数组来存储所有元素。例如,一个ArrayList拥有5个元素,实际数组大小为6(即有一个空位):

size=5

┌───┬───┬───┬───┬───┬───┐
│ A │ B │ C │ D │ E │   │
└───┴───┴───┴───┴───┴───┘

当添加一个元素并指定索引到ArrayList时,ArrayList自动移动需要移动的元素:

size=5

┌───┬───┬───┬───┬───┬───┐
│ A │ B │   │ C │ D │ E │
└───┴───┴───┴───┴───┴───┘

然后,往内部指定索引的数组位置添加一个元素,然后把size加1:

size=6

┌───┬───┬───┬───┬───┬───┐
│ A │ B │ F │ C │ D │ E │
└───┴───┴───┴───┴───┴───┘

继续添加元素,但是数组已满,没有空闲位置的时候,ArrayList先创建一个更大的新数组,然后把旧数组的所有元素复制到新数组,紧接着用新数组取代旧数组:

size=6

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ A │ B │ F │ C │ D │ E │   │   │   │   │   │   │
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

现在,新数组就有了空位,可以继续添加一个元素到数组末尾,同时size加1:

size=7

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ A │ B │ F │ C │ D │ E │ G │   │   │   │   │   │
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

可见,ArrayList把添加和删除的操作封装起来,让我们操作List类似于操作数组,却不用关心内部元素如何移动。

List主要接口方法

我们考察List<E>接口,可以看到几个主要的接口方法:

  • 在末尾添加一个元素:void add(E e)
  • 在指定索引添加一个元素:void add(int index, E e)
  • 删除指定索引的元素:int remove(int index)
  • 删除某个元素:int remove(Object e)
  • 获取指定索引的元素:E get(int index)
  • 获取链表大小(包含元素的个数):int size()

ArrrayList类

ArrayList类支持可随需要而增长的动态数组。ArrayList类对于使用索引取出元素有较高的效率,它可以使用索引来快速定位对象。但元素做删除或插入速度较慢,因为使用了数组,需要移动后面的元素已调整索引顺序。


┌───┬───┬───┬───┬───┬───┐
│ A │ B │ C │ D │ E │   │
└───┴───┴───┴───┴───┴───┘

因为它是动态数组,初始化大小容量4,当数据存满时扩容是以当前数组容量大小的2倍扩容,之后再把数组元素一个一个的存入,数组在扩容时浪费一定的内存空间,和存储时间,而且,元素添加是一个装箱的过程,所以说,跟一般的数组比起来,速度上差些。

LinkedList类

但是,实现List接口并非只能通过数组(即ArrayList的实现方式)来实现,另一种LinkedList通过“链表”也实现了List接口。在LinkedList中,它的内部每个元素都指向下一个元素:

       ┌───┬───┐   ┌───┬───┐   ┌───┬───┐   ┌───┬───┐
 HEAD ──>│ A │ ●─┼──>│ B │ ●─┼──>│ C │ ●─┼──>│ D │   │
        └───┴───┘   └───┴───┘   └───┴───┘   └───┴───┘

我们来比较一下ArrayList和LinkedList:

Java20-8-1.png

应用:ArrayList 和LinkedList

public class Main {
        List<String> lis = new LinkedList<>();
		
		/*添加元素*/
        lis.add("tony");
        lis.add("tom");
        lis.add("jack");
     
         
        System.out.println("<List原列表元素>:");
        for(int i=0;i<lis.size();i++){
            String result = (String)lis.get(i);
            System.out.println(result);
        }
        /*删除元素*/
        lis.remove(1);
        /*修改元素*/
        lis.set(1, "lucy");
        System.out.println("<删除元素后的List列表>:");    
                 
        for (int i = 0; i < lis.size(); i++) {
            String result = (String) lis.get(i);
            System.out.println(result);
        }
        System.out.println("---------------------------------");
        
        /*查找元素*/
        if(lis.contains("vivian")){
            System.out.println("包含此元素vivian!");
        }
        else{
            System.out.println("vivian该元素不存在!");
        }
}

练一练:集合的增删查改

练习(暂时不看)

用ArrayList集合重写Java任务:图书的接口处理里BookDataSet类的成员变量和方法。

答案:

package entity;
import java.util.*;
public class BookDataSet {
	 /*有商品的品种数,如num=5,代表目前经营5个品种的商品    */
     private int num=0;
	
	/*存放的商品*/
     private ArrayList<Goods> goods = new ArrayList<>();	
	
	
    public BookDataSet(){
    	
    }
     public BookDataSet(int num,ArrayList<Goods> goods){
    	
    	this.num =num;    	  	
    	this.goods=goods;
     }
    public void getGoods(){
    	System.out.println("站点商品明细:");
		//显示所有书籍    	
		for(int i=0;i<goods.size();i++) {
			System.out.println(goods.get(i).toString());
		}
    }
    public Goods getGoods(String id){
    	// 遍历所有的书籍信息
    	for(int i=0;i<this.num;i++){
    		if (this.goods.get(i).cid.equals(id)) {
    			return this.goods.get(i);
    		}
    	}
    	// 没有找到任何书籍信息抛出null
    	return null;
    }
    public void addGoods(Goods mygoods){
    	
    	    this.goods.add(mygoods);
    		num += 1;
    	  	
    }
    public void delGoods(Goods myGoods){
    	//将数组中myGoods条目对应的商品数量减为0
    	this.goods.remove(myGoods);
    }
    
    public void ModifyGoods(Goods myGoods){
    	//将数组中myGoods条目对应的信息修改一下
    	for(int i=0;i<goods.size();i++){
    		if (this.goods.get(i).cid==myGoods.cid) {
    			this.goods.set(i, myGoods);
    		}
    	}
    }
    @Override
 	public String toString() {
    	 int i;
		 String s="";
		 for(i=0;i<this.num;i++){
			 s +=goods.get(i).toString()+"\n";
		 }
		
		 return s;
 	}
	

}


返回 Java程序设计