1,集合类的由来:
对象是用于封装特有数据的,对象多了就需要存储起来,如果对象的个数不确定,就使用集合容器进行存储。
2,集合特点:
(1)用于存储对象的容器。
(2)集合的长度是可变的。
(3)集合中不可以存储基本数据类型值。
1,集合容器因为内部的数据结构不同,有多种具体容器,不断向上抽取,就形成了集合框架。
2,框架的顶层Collection接口:
Collection的常见方法:
(1)添加:
boolean add(Object obj);
boolean addAll(Collection coll);
(2)删除:
boolean remove(Object obj);
boolean removeAll(Collection coll);
void clear();//清空
(3)判断:
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();//判断是否为空
(4)获取:
int size();//获取大小
Iterator iterator();//取出元素的方式,迭代器
(5)其他:
boolean retainAll(Collection coll);//取交集
Object[] toArray();//将集合转成数组
import java.util.ArrayList; import java.util.Collection; public class CollectionDemo { public static void main(String[] args) { //Collection为接口,不能new接口,这里需要new一个实现了Collection接口的非抽象类。 Collection coll = new ArrayList(); show(coll); } public static void show(collection coll) { //1.添加元素 coll.add("abc1"); coll.add("abc2"); coll.add("abc3"); System.out.println(coll); //2.删除元素 coll.remove("abc2");//会改变集合的长度 //3.非空集合 coll.clear(); System.out.println(coll.contains("abc3"));//判断是否包含abc3 } }
import java.util.ArrayList; import java.util.Collection; public class CollectionDemo { public static void main(String[] args) { Collection c1 = new ArrayList(); Collection c2 = new ArrayList(); show(c1,c2); } public static void show(Collection c1,Collection c2) { //给c1添加元素 c1.add("abc1"); c1.add("abc2"); c1.add("abc3"); c1.add("abc4"); //给c2添加元素 c2.add("abc2"); c2.add("abc5"); c2.add("abc6"); System.out.println("c1 = " + c1); System.out.println("c2 = " + c2); //演示addAll c1.addAll(c2);//将c2中的元素添加到c1中 //演示removeAll boolean b = c1.removeAll(c2);//将两个集合中相同的元素从c1中删除 System.out.println("b = " + b); //演示containsAll boolean b1 = c1.containsAll(c2);//是否包含c2的所有元素 System.out.println("b1 = " + b); //演示retainAll boolean b2 = c1.retainAll(c2);//取交集,保留和指定集合相同的元素 System.out.println("b2 = " + b2); System.out.println("c1 = " + c1); } }
通过Iterator来迭代获取集合中的对象,通过集合对象获取其迭代器对象,以示例说明:
import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class IteratorDemo { public static void main(String[] args) { Collection coll = new ArrayList(); coll.add("abc1"); coll.add("abc2"); coll.add("abc3"); coll.add("abc4"); System.out.println(coll); /* 这里使用了Collection中的iterator()方法,调用集合中的迭代器方法 是为了获取集合中的迭代器对象 */ //这种方式获取的迭代器,在循环结束后,变量it仍然占用内存,若循环结束后仍然使用it,则使用这种方式 Iterator it = coll.iterator(); while(it.hasNext()) { System.out.println(it.next()); } //下面这种方式一般比较常用,it为局部变量,循环结束后自动释放空间 for(Iterator it = coll.iterator();it.hasNext();) { System.out.println(it.next()); } } }
Iterator iterator();迭代器,一种取出元素的方式。
这个迭代器对象必须依赖于具体的容器,因为每一个集合数据结构都不同,所以该迭代器对象是在容器中进行内部实现的。查其源码,会发现他的实现是内部类的形式。
对于容器实现者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器对象即可,也就是iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口,其实他就是抓娃娃机中的那个夹子,我们只需要投币,操作摇杆即可,并不需要知道里面的夹子是如何工作的,但是由于每个抓娃娃机的内部结构不同,里面的夹子的抓法也不同,但是对于外面操作的我们来说,都只是操作摇杆。
1,Collection有两个已实现的子接口较为常用,List(列表)和Set(集)。
2,特点:
Collection
|--List(列表):有序(存入和取出的顺序一致);元素内有索引(角标);元素可以重复。
|--Set(集):元素不能重复,无序。
1,List特有的常见方法,有一个共性的特点就是操作角标。
(1)添加:
void add(index,element);//在指定位置添加一个元素
void add(index,collection);//在指定位置添加一堆元素
(2)删除
Object remove(index);//返回被删除的元素
(3)修改
Object set(index,element)//返回被修改的元素
(4)获取
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from, to);//返回一个区间的元素,包括from不包括to
2,演示
import java.util.ArrayList; import java.util.List; public class ListDemo { public static void main(String[] args) { List list = new ArrayList();//ArrayList也是List的子接口 show(list); } public static void show(List list) { //添加元素 list.add("abc1"); list.add("abc2"); list.add("abc3"); System.out.println(list); //插入元素 list.add(1,"abc9"); //删除元素 System.out.println("remove:" + list.remove(2)); //修改元素 System.out.println("set:" + list.set(1,"abc8")); //返回abc2,返回被修改的元素 //获取元素 System.out.println("get:" + list.get(0));//abc1 //获取子列表 System.out.println("sublist:" + list.subList(1,2));//返回abc2,包含头不包含尾 } }
import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; public class ListDemo { public static void main(String[] args) { List list = new ArrayList(); //show(list); list.add("abc1"); list.add("abc2"); list.add("abc3"); list.add("abc4"); System.out.println("list" + list); ListIterator it = list.listIterator();//获取列表迭代器对象 //它可以实现在迭代过程中完成对元素的增删改查 //注意:只有list集合具备该迭代功能 while(it.hasNext()) { Object obj = it.next(); if(obj.equals("abc2")) { //如果是abc2则改为abc9 it.set("abc9"); } } //System.out.println("hasNext:" + it.hasNext()); //下一个元素 //System.out.println("hasPrevious:" + it.hasPrevious()); //前一个元素 while(it.hasPrevious()) { System.out.println("previous : " + it.previous()); } System.out.println("list:" + list); /* Iterator it = list.iterator(); while(it.hasNext()) { /* java.util.ConcurrentModificationException,在迭代器过程中, 不要使用集合操作元素,容易出现异常,可以使用Iterator接口的子接口 ListIterator来完成在迭代中对元素进行更多的操作。 */ Object obj = it.next(); if(obj.equals("abc2")) { list.add("abc9"); } else { System.out.println("next:" + obj); } } System.out.println(list); */ } public static void show(List list) { list.add("abc1"); list.add("abc2"); list.add("abc3"); list.add("abc4"); Iterator it = list.iterator(); while(it.hasNext()) { System.out.println("next:" + it.next()); } //list特有的取出元素的方式之一 for(int x=0;x<list.size();x++) { System.out.println("get:" + list.get(x)); } } }
在用/* ... */注释掉的内容中,it是Iterator对象,list是List对象,两个对象同时操作可能会引发异常,它上面的方法用的是ListIterator来获取列表迭代器对象,可以用List中的listIterator方法来获取。如:ListIterator it = list.listIterator();方法获取了list列表的列表迭代器对象it,可以用it直接对list中的元素操作,就不会出现异常,因为都是在列表下操作的对象,不涉及操作的并发问题。
1,List:
|--Vector:内部是数组数据结构,是同步的,增删,查询都很慢。
|--ArrayList:内部是数组数据结构,是不同步的,替代了Vector,查询的速度很快。
|--LinkedLst:内部是链表数据结构,是不同步的,增删元素的速度很快。
2,ArrayList:
如果要删除b,则b删除后其后面的元素都要向前移动,若加入一个进来,要将插入位置的后面的元素都向后移动一格,才能插入,牵一发而动全身,增删效率差。
LinkedList:(链表)
加入a的地址为22,b的地址为33,c的地址为44,a中的指针为33,将a和b链接起来,b中的指针是44,将b和c链接起来。若要删除b,直接将c的地址44记录到a中替换掉33就可以了;若要把b加入,将b的33记录到a中,c的44记录到b中即可,增删块,但是查询不方便。
ArrayList为什么查询快?
因为ArrayList底层为数组结构,有角标,在堆中是一片连续的内存空间,用角标查询速度快。
LinkedList为什么查询慢?
因为LinkedList底层是链表结构,虽然也有角标,但他不是连续的内存空间,查询是仍需要通过内存地址查询,效率低。