6.3 集合框架
6.3.1简述
1、由来
对象用于封装特有数据,对象多了需要存储,且对象的个数不确定,于是 SUN公司专门设计了一组类,这组类因内部的数据结构不同,不断向上抽取,就形成了各种不同的具体容器,即容器类,这些容器共同组成了集合框架(Collection Framework)。集合框架包含在java.util 包中。
任何集合框架都包含三大块内容:对外的接口、接口的实现和对集合运算的算法。
2、 从体系上讲,集合框架可分为两种:
①:Collection 接口:
・Set:集,无序性,无重复
・List:列表,以线性方式存储,只能在头或尾添加,或者在指定的位置后面插入新对象
②:Map 接口。
整个框架如下图:
3、特点
・集合用于存储对象。
・集合的长度是可变的
・集合中不可以存储基本数据类型
4、集合与数组的区别
・数组的长度是固定的;集合长度是可变的。
・数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
・数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型
6.3.2 Collection
java.util.collection接口是描述Set和List集合类型的根接口。
1、集合操作的常见方法,包括:
以代码的形式介绍:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public void CollectionDemo{ public static void main(String[] args){ Collection c1 = new ArrayList(); Collection c2 = new ArrayList(); show(); } public static void show(Collection coll){ //1、添加元素(add) c1.add("hufei1"); c1.add("hufei2"); System.out.println(c1);//测试代码 c2.add("hufei3"); c2.add("hufei4"); c2.add("hufei1"); c1.addAll(c2);//将c2中的元素添加到c1中 System.out.println(c1);//测试代码 //2、删除元素 c1.remove("hufei1");//删除hufei1元素,同时改变了集合的长度 System.out.println(c1);//测试代码 c1.clear();//清空集合 System.out.println(c1);//测试代码 c1.removeAll(c2);//将俩个集合中的相同的元素从调用该的集合删除 System.out.println(c1);//测试代码 //3、判断元素 System.out.println(c1.contain("hufei2"));//测试代码 System.out.println(c1.containAll(c2));//测试代码 System.out.println(c1.retainAll(c2));//取交集,保留俩集合相同的元 //素,除此之外还有isEmpty(),containAll(collection c), //4、获取元素(Iterator) //下面的代码会详述 }
2、关于迭代器
定义:按次序一个一个的获取集合中的所有对象
使用迭代器的基本机制:
集合―>迭代器―>hasNext()测试―真―>连续调用next()方法―>对象
―假―>不再有对象有效
迭代器原理:在集合框架中,容器种类很多,每种容器的数据结构都有自己的特点,而要取出其中的元素,就必须依赖于具体容器来实现迭代器,从而创造自己独有的迭代器,这个迭代器必须做俩件事,判断有没有元素和取出元素,即hasNext()和next(),把这些容器的独有迭代器向外抽取就形成了Iterator接口。他是对所有的Collection容器进行元素取出的公共接口
接上的代码:
//与forEach相结合 Iterator it = c1.Iterator(); for(it.hasNext()){ //以上代码也可写成for(Iterator it = c1.Iterator();it.hasNext()) System.out.println(it.next()); } //与while相结合 Iterator it = c1.Iterator(); while(it.hasNext()){ System.out.println(it.next()); //它与for循环的区别在于在代码结束后,引用还留在内存中,所以是否用它视 //情况而定 }
6.3.3 List
1、常见方法
1)、常见方法的共同特点:可以操作角标
2)、以代码的形式介绍方法:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; public class ListIterator { public static void main(String[] args){ List list = new ArrayList(); show(list); } public static void show(List list){ //1、添加元素(add) list.add("hufei1"); list.add("hufei2"); list.add("hufei3"); System.out.println(list); //2、删除元素 System.out.println(list.remove(0));//删除角标为2的元素,同时 //改变了集合的长度 //3、修改元素 System.out.println(list.set(1, "hufei4"));// //4、获取元素 System.out.println(list.get(0));//测试代码 //5、获取子元素 System.out.println(list.subList(1, 2));//返回指定的 角标1(包 //括 )和 角标2(不包括)之间的子元素 } }
2、ListIterator接口
1)、list获取元素的方法
接上面的代码:
/获取元素的方法一 Iterator it = list.Iterator(); for(it.hasNext()){ System.out.println(it.next()); } //获取元素的方法二 for(int x = 0; x < List.size()); x++){ System.out.println(list.get(x));//list独有的方法 }
2)、由来(利用代码解释)
importjava.util.Iterator; importjava.util.List; classListIteratorDemo{ publicstaticvoidmain(String[] args){ list.add("hufei1"); list.add("hufei2"); list.add("hufei3"); Iterator it = list.Iterator(); while(it.hasNext()){ Object obj = it.next();//用Object的原因是在add方法添加时,就加的是 //Object对象, if(obj.equals("hufei2")) list.add("hufei4"); //这样做会发生ConcurrentModificationException异常,因为list与 //Iterator同时发生, else System.out.println(obj); } System.out.println(list); } }
由于在迭代器过程中,使用集合操作元素,容易出现异常,所以可以使用Iterator接口的子类接口ListIterator来完成在迭代中对元素进行更多的操作。
以上迭代器的代码可改为以下代码:
java.util.ListIterator it = list.listIterator(); while(it.hasNext()){ Object obj = it.next(); if(obj.equals("hufei2")) it.add("hufei5"); System.out.println(obj);
3、ListIterator的常见方法
ListIterator可以在迭代过程中实现增删改查,而且只有List集合具备该迭代功能
hasNext();以正向遍历列表时,如果列表迭代器有多个元素,则返回 true
hasPrevious();如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
nextIndex() 返回对 next 的后续调用所返回元素的索引。
4、List常用子类
lVector:内部是数组数据结构,是同步的
Vector只保存对象的引用,而不是实际对象
lArrayList:内部是数组数据结构,是不同步的,替代了Vector,由于空间连续,所以查询的速度快
import java.util.ArrayList; import java.util.Iterator; public class ArrayListTest { /** * ArrayList集合存储自定义对象的 */ public static void main(String[] args) { ArrayList al = new ArrayList();//初始容量为 10 的空列表 al.add(new Person("zhangsan1",21)); al.add(new Person("zhangsan2",22)); al.add(new Person("zhangsan3",23)); al.add(new Person("zhangsan4",24)); al.add(5);//自动装箱,基本数据类型赋值给引用数据类型al.add(5) //相当于al.add(new Integer(5)) Iterator it = al.iterator(); while(it.hasNext()){ //System.out.println(it.next().getName); //失败的原因,在add的时候,已经自动将Person提升为Object类 //型了,但Object中没有getName方法 //System.out.println(((Person)it.next()).getName()+"::" //+((Person)it.next()).getAge());//在里面放俩个next,它会指向下一个数据,会输出zhangsan1::22 zhangsan 3 : :24,会出现问题,所以代码应该如下: Person p = (Person) it.next(); //多次调用it.next()先给它取个名字 System.out.println(p.getName()+"::"+p.getAge()); } } }
将以下代码放置于另一个java文件中
public class Person{ private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); // TODO Auto-generated constructor stub } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
lLinkedList:内部是链表数据结构,是不同步的。增删元素速度快
面试题:
import java.util.Iterator; import java.util.LinkedList; class Queue{ private LinkedList link; Queue(){ link = new LinkedList(); } public void myAdd(Object obj){ link.add(obj); } public Object myGet(){ return link.removeLast();// 队列:先进先出(FIFO) //return link.removeFirst();//堆栈:先进后出(FILO) } public boolean isNull(){ return link.isEmpty(); } } public class InterviewTest { /* * 请使用LinkedList来模拟一个堆栈或者队列数据结构容器, * 即描述这样一个容器,给使用对象提供一个容器完成这俩种结构的一种 * 堆栈:先进后出(FILO) * 队列:先进先出(FIFO) */ public static void main(String[] args) { Queue q = new Queue(); q.myAdd("hufei1"); q.myAdd("hufei2"); q.myAdd("hufei3"); while(!q.isNull()){ System.out.println(q.myGet()); } } }