接着上一篇,接着讲讲集合的知识。上一篇讲了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);//打印元素 } }
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; } }