JAVA常用集合框架用法详解基础篇二之Colletion子接口List

接着上一篇,接着讲讲集合的知识。上一篇讲了Collection接口。它可以说是集合的祖先了,我们这一篇就说说它的子孙们。

一、Collection的子接口

List:有序(存入和取出的顺序一致),元素都有索引(即角标),元素可以重复。

Set:元素不能重复,无序的。


首先讲讲List。 

A、List特有的常见方法(都有一个共性的特点就是可以操作角标)。List接口是可以完成对元素的增删改查,List接口的实现是通过子类来完成:

现在我们初始化一个List接口:List  ll=new ArrayList();

接下来说说List的主要常用的方法。

1、添加(通过索引的位置来添加元素)

void add(index,element);
void add(index,Collection)
 //List特有的取出方式之一
for(inti=0;i<ll.size();i++){
     System.out.println(ll.get(i));
 }

         2、删除(删除相应索引位置的元素)

Object      remove(index);//返回被删除的元素

         3、修改(修改指定索引位置的元素,并返回修改前的元素)     

ObjectSet(index,element)//返回被修改的元素

         4、获取:

Object get (index);
int  IndexOf(object);//返回此列表中第一次出现指定元素的索引,如果此列表不包含该素,则返回-1.
int lastIndexOf(object);//返回此列表中最后一次出现指定的元素,如果此列表不包含该元素,则返回-1.
List subList(int from,int to);//包含头,不包含尾,获取子列表。

测试程序代码如下:

代码如下:
package com.wq.list;
/**
 * 添加一个课程类,提供课程的选择
 * @author LULEI
 *
 */
public class Courses {
	private String id;//课程序号
	private String name;//课名
	
	public Courses(){
		
	}
	public Courses(String id,String name){
		this.setId(id);
		this.setName(name);
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	
}

//测试List的一些方法:

package com.wq.list;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class ListTest {
	//用于存放备选课程的List
	public List courseToSelect;
	public ListTest(){
		this.courseToSelect=new ArrayList();
	}
	
	//用于courseToSelect添加备选课程
	public void testAdd(){
		//创建一个课程的实例,并通过使用add方法,将该实例
		//添加到备选课程List中
		Courses cr1=new Courses("1", "数据库");
		courseToSelect.add(cr1);//将课程添加到备选课程List中
		Courses temp=(Courses)courseToSelect.get(0);//选取List列表中的第一个元素
		System.out.println("添加了课程:"+temp.getId()+"."+temp.getName());
		
		Courses cr2=new Courses("2","JAVA");
		courseToSelect.add(0, cr2);
		Courses temp2=(Courses)courseToSelect.get(0);
		System.out.println("添加了课程:"+temp2.getId()+"."+temp2.getName());
		
		/*
		 * 下面代码会出现越界的异常
		Courses cr3= new Courses("4", "test");
		courseToSelect.add(4,cr3);
		//Courses cr3=(Courses)courseToSelect.get(4);
		//System.out.println("添加了课程:"+cr3.getId()+"."+cr3.getName());
		 * 
		 */
		
		Courses cr7=new Courses("1", "数据库");
		courseToSelect.add(cr7);//将课程添加到备选课程List中
		Courses temp7=(Courses)courseToSelect.get(2);//选取List列表中的第一个元素
		System.out.println("添加了课程:"+temp7.getId()+"."+temp7.getName());
		//addAll()方法的使用
		Courses[] cr3={new Courses("3","高数"),new Courses("4","英语")};
		courseToSelect.addAll(Arrays.asList(cr3));//将数组转换成List集合
		Courses temp3=(Courses)courseToSelect.get(3);
		Courses temp4=(Courses)courseToSelect.get(4);
		
		System.out.println("添加了两门课:"+temp3.getId()+"."+temp3.getName()
				+temp4.getId()+"."+temp4.getName());
		
		Courses[] cr4={new Courses("5","高等语文"),new Courses("6","数据处理")};
		courseToSelect.addAll(2,Arrays.asList(cr4)); //将数组转换成List集合

		Courses temp5=(Courses)courseToSelect.get(2);
		Courses temp6=(Courses)courseToSelect.get(3);
		
		System.out.println("添加了两门课:"+temp5.getId()+"."+temp5.getName()
				+temp6.getId()+"."+temp6.getName());
		
	}
	
	/**
	 * 创建一个Get方法,用于获取List中的元素的方法
	 */
	public void testGet(){
		int num=courseToSelect.size();//获取List的长度
		System.out.println("可以选择的课程如下:");
		for(int i=0;i<num;i++){
			Courses cr=(Courses) courseToSelect.get(i);
			System.out.println(cr.getId()+"."+cr.getName());
		}
	}
	
	/**
	 * 使用迭代器的方法来获取List中的元素
	 * @param args
	 */
	public void testIterator(){
		//迭代器是个借口,依赖集合存在
		Iterator i=courseToSelect.iterator();
		System.out.println("可以选择的课程如下(通过迭代器实现的):");
		while(i.hasNext()){
			Courses cr=(Courses)i.next();
			System.out.println(cr.getId()+"."+cr.getName());
		}
	}
	
	/**
	 * 使用for each的方法来获取List中的元素
	 * @param args
	 */
	public void testForEach(){
		System.out.println("可以选择的课程如下(通过foreach实现的):");
		for(Object obj:courseToSelect){
			Courses cr=(Courses)obj;
			System.out.println(cr.getId()+"."+cr.getName());
		}
	}
	
	/**
	 * 通过set()方法来修改List元素
	 * @param args
	 */
	public void testModify(){
		courseToSelect.set(4, new Courses("7", "毛概"));
		}
	
	
	/**
	 * 学会使用remove()方法来删除List中的元素
	 * 这种方法的参数是obj,还有一种remove方法的参数是索引、
	 * 如:remove(4);即可获得同样的效果
	 * @param args
	 */
	public void testRemove(){
		Courses cr=(Courses) courseToSelect.get(4);
		System.out.println("将要删除的课程是:"+cr.getId()+"."+cr.getName());
		courseToSelect.remove(cr);
		System.out.println("课程已删除");
		testForEach();
	}
	
	
	/**
	 * 使用removeAll()方法来删除多个List中的对象
	 * @param args
	 */
	public void testRemoveAll(){
		Courses[] crs={(Courses) courseToSelect.get(4),
				(Courses) courseToSelect.get(5)};
		//removeAll的参数是一个集合,所以要将
		//Courses数组转换成集合List
		courseToSelect.removeAll(Arrays.asList(crs));
		testForEach();
	}
	
	/**
	 * 创建一个奇怪的方法,用来给List添加字符串
	 * @param args
	 */
	public void testAddString(){
		System.out.println("到底能不能添加字符串呢!!");
		courseToSelect.add("这是一个很无辜的字符串");
	}
	
	public static void main(String[] args){
		ListTest lt=new ListTest();
		lt.testAdd();
		lt.testGet();
		
		lt.testIterator();
		lt.testAddString();
		lt.testForEach();
//		lt.testModify();
//		lt.testForEach();
//		lt.testRemove();
//		lt.testRemoveAll();
	}
}


注意上面的例子我没有使用Iterator迭代器,而是使用了foreach语句。不过,接下来我们看看一个使用迭代器遍历集合出错的代码:

主要代码如下:

    

..........
ll.add(“qwe1”);
ll.add(“qwe2”);
ll.add(“qwe3”);
Iterator  it=ll.iterator();//获取List集合的迭代器的对象
while(it.hasnext()){
       Object  obj=it.next();
        if(obj.equals(“qwe2”)){
              ll.add(“abc9”);//在迭代器中给集合添加元素
            }
         else{
             System.out.println(“next:”+obj);//打印元素
                     }
       }     

以上就是一段代码,但是在运行while循环中会出现异常:Java.util.concurrentModificationException。主要的原因是:在迭代器过程中,不要直接使用集合来操作元素,容易抛出异常。怎么解决呢???我们可以使用Iterator的子接口ListIterator来完成在迭代器中对元素进行更多的操作。

更换代码如下:

       ll.add(“qwe1”);
       ll.add(“qwe2”);
       ll.add(“qwe3”);
       ListIterator  it=ll.listiterator();//获取List集合的迭代器的对象
       while(it.hasnext()){
              Object  obj=it.next();
              if(obj.equals(“qwe2”)){
                     it.add(“abc9”);//迭代器对象进行添加元素
                     }
              else{
              System.out.println(“next:”+obj);//打印元素
                     }
       }  

好,使用ListIterator就可以实现修改集合的操作。我们可以在迭代器中完成增加和删除的操作,修改后的结果会直接映射到集合中的。   


B、List的子类总结

Vector:内部是数组数据结构,是同步的(即线程安全的)。增删修改查询都很慢。(不常用)

ArrayList:内部是数组数据结构的,是不同步的。替代了Vector,查询的速度快。

LinkedList:内部是双向链表的数据结构,是不同步的。增删元素的速度非常快。

这里我们做一个练习:使用LinkedList来模拟一个堆栈和队列的数据结构。

堆栈:先进后出(First In Last Out)FILO

队列:先进先出(First In First Out)FIFO


我们应该描述这样一个容器,给使用者提供一个容器对象完成这两种结构的一种。LinkedList(可以实现队列和堆栈的功能)常用的方法如下:

---添加

addFirst();

addLast();//从jdk1.6后改成 offerFirst(),和offerLast();

---获取

getFirst();//获取但不移除,如果链表为空。抛出NoSuchElementException

getLast();

从jdk1.6后上面两个改成:

peekFirst();//获取但不移除,如果链表为空,则返回null

peekLast();

---删除

removeFirst();//获取,且移除当前的元素。如果链表为空。抛出NoSuchElementException

removeLast();

从jdk1.6后上面两个改成:

poolFirst();//获取且移除当前的元素,如果链表为空,则返回null

poolLast();

 

 

代码的实现如下:

///队列类
package com.wq.linkedlist;

import java.util.LinkedList;
import java.util.List;

public class DuiLie {
	//这个类是实现队列的功能的
	LinkedList ls=new LinkedList();//内部是链表结构的list
	public DuiLie(){
		
	}
	public void addElement(Object obj){
		//ls.addLast(obj);//在后面添加元素
		ls.offerLast(obj);//jdk1.6版本后的在后面添加元素方法
		System.out.println(obj+"已经加入队列");
	}
	public void removeElement(){
		Object obj=ls.pollFirst();//jdk1.6版本的删除最前面的元素,取代了removeFirst()方法
		System.out.println(obj+"已经出队列");
	}
}


///堆栈类
package com.wq.linkedlist;

import java.util.LinkedList;

public class DuiZhan {
	//这个类是实现堆栈的功能的
		LinkedList ls=new LinkedList();//内部是链表结构的list
		public DuiZhan(){
			
		}
		public void addElement(Object obj){
			//ls.addLast(obj);//在后面添加元素
			ls.offerLast(obj);//jdk1.6版本后的在后面添加元素方法
			System.out.println(obj+"已经加入堆栈");
		}
		public void removeElement(){
		Object obj=ls.pollLast();//jdk1.6版本的删除最前面的元素,取代了removeLast()方法
			System.out.println(obj+"已经退出堆栈");
		}
}


/////测试上述两个类
package com.wq.linkedlist;

public class test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		DuiZhan dz=new DuiZhan();//实例化堆栈的对象
		DuiLie dl=new DuiLie();//实例化队列的对象
		
		//实现堆栈的功能
		System.out.println("实现堆栈的功能");
		dz.addElement(111);
		dz.addElement(222);
		dz.addElement(333);
		dz.addElement(444);
		
		dz.removeElement();
		dz.removeElement();
		dz.removeElement();
		dz.removeElement();
		System.out.println();
		
		//实现队列的功能
		System.out.println("实现队列的功能");
		dl.addElement(111);
		dl.addElement(222);
		dl.addElement(333);
		dl.addElement(444);
		
		dl.removeElement();
		dl.removeElement();
		dl.removeElement();
		dl.removeElement();
		
	}

}

运行结果如下:

实现堆栈的功能
111已经加入堆栈
222已经加入堆栈
333已经加入堆栈
444已经加入堆栈
444已经退出堆栈
333已经退出堆栈
222已经退出堆栈
111已经退出堆栈
 
实现队列的功能
111已经加入队列
222已经加入队列
333已经加入队列
444已经加入队列
111已经出队列
222已经出队列
333已经出队列
444已经出队列

C、ArrayList集合存数自定义对象

1、这里,我要提一下。集合里存储的都是对象的引用(就是对象在堆中的绝对地址的值),迭代器里迭代的也是集合中的对象引用。

代码如下:

package com.wq.arraylist;

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

import com.wq.person.Person;

/**
 * 该类主要完成 去除ArrayList中的重复元素
 * @author LULEI
 *
 */
public class testArrayList {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		List li=new ArrayList();
		
		testDemo1(li);
	}

	public static void testDemo1(List li) {
		//测试传统的对象
		/*
		li.add("111");
		li.add("111");
		li.add("222");
		li.add("333");
		li.add("444");
		li.add("333");
		*/
		
		/*
		 * 测试添加自定义的对象Person
		 */
		li.add(new Person("wq1",21));
		li.add(new Person("wq2",22));
		li.add(new Person("wq1",21));
		li.add(new Person("wq3",23));
		li.add(new Person("wq2",22));
		li.add(new Person("wq3",23));
		System.out.println(li);
		
		//调用换取单个元素的方法
		li=getSingelElement(li);
		System.out.println(li);
	}

	public static List getSingelElement(List li) {
		// TODO Auto-generated method stub
		List temp=new ArrayList();//新建一个List
		for(Iterator it=li.iterator();it.hasNext();){
			Object obj=it.next();
			if(!temp.contains(obj)){//如果不包含该元素
				temp.add(obj);//添加到新的List中
			}
		}
		return temp;
	}

}
这里就先这样,下一篇将介绍Set接口。

你可能感兴趣的:(JAVA常用集合框架用法详解基础篇二之Colletion子接口List)