集合类
集合类就是用于存储对象的一种方式。
数组和集合类同是容器(存储的都是对象的引用或者地址),它们的不同在于:数组既可以存储基本数据类型数据,也可以存储对象,但存储后的长度是固定的;集合的长度是可变的,且集合只能存储对象。
集合类的特点:集合只能用于存储对象,其长度是可变的,并且可以存储不同类型的对象。
集合容器是许多容器根据自身的一些共性不断的向上抽取得到的一个体系(collection接口)。自身特点就是指存储数据的数据结构。
集合最共性的功能:
1,添加元素。
boolean add(element):添加一个元素。从尾部添加。
boolean addAll(Collection):添加一个集合进来,将这个集合中的元素,都添加到指定的集合中。
2,删除元素。
void clear():清空集合中。删除集合中所有的元素。
boolean remove(object):删除指定的元素。且删除后,容器长度会发生改变,而数组做不到这一点!
boolean removeAll(collection):按照指定的集合中的元素,将当前集合中的一批元素删除。注意:集合间取交集只保留两集合间的相同元素,只有集合前后元素发生改变时返回值为true,否则为false。
3,判断元素。
boolean isEmpty():判断集合中的元素是否为空。
boolean contains(object):判断集合是否包含某一个元素。
boolean containsAll(collection):判断集合是否包含一批元素。
4,获取元素。
Iterator iterator():这是集合特有的取出元素的方式。迭代器。需要通过两个动作来完成:先判断,后获取。这个方法很重要!
其他功能:
1,获取集合的长度。int size():获取集合中元素的个数。
2,将集合转成数组:toArray():
3,取交集:boolean retainAll(Collection):
通过对上述方法的观察可以得出一条基本规律:方法名后带有All的都是集合与集合之间的关系!
*/
//导入包中的类。
import java.util.*;
class CollectionDemo
{
public static void sop(String str)
{
System.out.println(str);
}
public static void main(String[] args)
{
method_2();
}
//演示带All的功能。
public static void method_2()
{
Collection coll1 = new ArrayList();
coll1.add("abc1");
coll1.add("abc2");
coll1.add("abc3");
coll1.add("abc4");
Collection coll2 = new ArrayList();
coll2.add("abc2");
coll2.add("abc4");
coll2.add("abc9");
sop("coll_1 : "+coll1);
sop("coll_2 : "+coll2);
//演示addAll();
coll1.addAll(coll2);//将coll2中的元素添加到coll1中。
sop("coll_1 : "+coll1);
//演示removeAll();
coll1.removeAll(coll2);//将coll1和coll2相同的元素从coll1中删除。
sop("coll_1 : "+coll1);//打印剩余的集合元素
//演示containsAll();
sop("containsAll : "+coll1.containsAll(coll2));
//演示retainAll();
/*
retainAll方法:只要被取交集的集合元素发生改变。返回true。
如果没有改变。返回false。
如果coll1和coll2取交集,没有相同元素。那么coll1取完后,元素个数为0.相当于集合清空。
如果coll1和coll2元素一致。不会取交集,coll1不发生改变。
*/
sop("retainAll : "+coll1.retainAll(coll2));
sop("coll_1 : "+coll1);
}
public static void method_1()
{
//创建了一个集合对象。也就是在内存中有了一个可以存储对象的容器。
Collection coll = new ArrayList();
//添加元素。
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
coll.add("abc4");
//删除。只要删除成功,长度就会改变。
//System.out.println("remove:"+coll.remove("abc3"));
//清除。
coll.clear();
//判断。
//sop("contains:"+coll.contains("abc11"));
//判断集合是否为空。其实就是在判断size是否是0.
sop("isEmpty:"+coll.isEmpty());
//想要将集合中的元素打印出来看一下。
System.out.println(coll);
//获取集合的长度。
System.out.println("size="+coll.size());
}
}
/*
演示:迭代器。Iterator
迭代器:就是集合取出元素的方式。
迭代器就是一个容器内部的取出方式。因为每一个容器数据结构不一样。
所以取出的具体细节也不同。迭代器需要依赖具体的容器。同时
还在直接访问容器中的内容。
所以就将取出方式对应的类定义到了容器类的内部。
用内部类来完成描述。
通过对外暴露公共的访问方式来操作该取出方式对象。
所以就对外提供了Iterator接口。这个接口也可以提高扩展性。
当有了新的容器出现时,如果该容器也应该具有取出方式,
那么该容器内部也可以定义一个内部类来实现接口定义自己的取出细节。
但是对于使用该容器的使用者只要持有这个迭代器接口既可以操作
该容器中的元素。
这样就降低了耦合性。
*/
import java.util.*;
class IteratorDemo
{
public static void main(String[] args)
{
Collection coll = new ArrayList();
coll.add("abc1");
coll.add("abc2");
coll.add("abc3");
coll.add(4);//jdk1.4是必须coll.add(new Integer(4));在jdk1.5时,add(4)是可以的。因为支持自动拆装箱。
//如何取出元素呢?
//通过集合的迭代器来完成。这个迭代器对象已经在集合内部创建完毕了。通过一个方法获取即可。iterator();
Iterator it = coll.iterator();//获取该集合的迭代器对象。
//要取出元素之前要先判断是否有元素。
/*
next():方法会自动一个一个的往下取。
当没有元素了,还在进行取的动作,就会出现NoSuchElementException没有这个元素异常。
所以 我们每取一次,都要判断一次,是否有下一个。
所以需要循环判断。
所以总结: 获取元素步骤:先判断,在获取。
*/
//取出上面的四个元素的第一种方法
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
//取出上面的四个元素的第二种方法
while(it.hasNext())
{
System.out.println(it.next());
}
/*
for(Iterator it = coll.iterator(); it.hasNext(); ) //这是在开发中使用的格式!
{
System.out.println(it.next());
}
*/
}
}
在collection下面有两个常见的子集合体系(子接口),即List和Set。
List的特点:该体系对元素有索引,有序(存入和取出的顺序一致),同时可以重复存储元素(因为元素有角标)。
Set的特点:该体系容器的元素是不一致的(存入和取出的顺序可能不同),同时不可以存储相同的元素。
List子接口(重点中的重点)
该接口具有的功能更为强大,使用起来更为方便!务必掌握!!
因为List也是不断抽取出来。所以它里面定义了该体系中共性的功能。
所以将其共性基本功能搞定.
添加:
void add(index,element):在指定的索引位插入元素。
boolean addAll(int index, Collection<? extends E> c) :在指定的位置插入一批元素。
删除:
Object remove(int index) :通过索引来删除元素,并返回被删除的元素。
获取:
Object get(index):通过索引获取指定位置上的元素。
int indexOf(object):根据元素获取该元素在list中的位置。如果不存在返回-1.
int lastIndexOf(object);根据元素反向获取该元素在list中的位置。如果不存在返回-1.
List subList(start,end):获取列表中的一部分元素。返回的还是一个列表。包含start位,不包含end位。
ListIterator listIterator() : 它支持一个特殊的迭代器。就是列表迭代器。它本身是Iterator的一个子接口。
修改:
Object set(index,Object):替换指定位置的元素,并返回被替换的元素。
也就是说:List集合具备对元素的增删改查。
对于List集合获取所有元素。有两种方式:
1,迭代器 ,Collection体系中的共性功能。
2,通过for+get()方法 ,list集合特有的方式。
范例:
import java.util.*;
class ListDemo
{
public static void sop(String str)
{
System.out.println(str);
}
public static void main(String[] args)
{
//创建一个list集合。
List list = new ArrayList();
//添加要演示的元素。
list.add("abc1");
list.add("abc2");
list.add("abc3");
sop("原集合 :"+list);
//插入。
list.add(1,"abc9");//如果角标不存在。会出现IndexOutOfBoundsException
//删除。
sop("remove : " +list.remove(2));
//修改。
sop("set : "+list.set(0,"abc88"));
//获取元素的索引位。
sop("index : "+list.indexOf("abc2"));
//获取子列表。
List subList = list.subList(0,1);
sop("subList : "+subList);
sop("list:"+list);
//通过索引获取元素。
sop("get :"+list.get(1));
//获取到该集合中的所有的元素。
for(int x = 0; x < list.size(); x++)
{
sop("list.get("+x+")="+list.get(x));
}
//再使用迭代器获取一遍。
Iterator it = list.iterator();
while(it.hasNext())
{
sop("next :"+it.next());
}
}
}
ArrayList,LinkedList和Vector的各自特点及相互间的比较
List:有序,可重复,有索引。
|--ArrayList:底层是数组数据结构。是线程不同步的。查询元素的速度很快。但是增删元素的效率稍低。
|--LinkedList:底层是链表数据结构,是线程不同步的。查询元素的速度稍慢,但是增删速度很快。
|--Vector:底层也是数组数据结构。是线程同步的。被ArrayList替代了。查询速度,和增删的速度非常慢。效率低。
可变长度的数组的原理:
当默认长度为10的数组不够存储时,会建立一个新数组。
将原来数组中的元素复制到新数组中。把后面添加进来的元素存储到新数组中。
ArrayList:创建新数组是50%延长
Vector:创建新数组是100%延长。
所以ArrayList比Vector效率高。
List接口的特有方法ListIterator迭代器
演示列表迭代器。
这个是List集合特有的迭代器。
这个列表迭代器接口是迭代器接口的子接口。
注意:
当在对元素进行迭代时,如果在迭代器过程中又使用了集合对象在操作元素。
就容易发生ConcurrentModificationException 并发修改异常。
因为在获取该集合迭代器时,迭代器已知的是集合现有的元素。
可是在迭代器过程中,用集合对象操作元素。迭代器是不知道的。
所以在迭代过程中就会出现问题。
解决:
如果想要在迭代器中需要对集合的元素进行操作,比如:添加元素。
只能使用迭代器对象来完成。
可是很遗憾:Iterator 具备的功能只有三个。hasNext(判断) next(获取) remove(删除)
它并不具备添加动作。
所以这时,可是用List集合特有的迭代器。列表迭代器。ListIterator。
ListIterator具备的功能非常多:在迭代器过程中,增删改查都没有问题。
增:add();
删:remove();
改:set();
查:next()
判断:hasNext();
因为list集合有角标。
还可以逆向遍历。
判断 hasPrevious();
获取 previous()
注意:列表迭代器只有List集合具备。
*/
import java.util.*;
class ListIteratorDemo
{
public static void main(String[] args)
{
List list = new ArrayList();
list.add("abc1");
list.add("abc2");
list.add("abc3");
list.add("abc4");
//Iterator it = list.iterator();
ListIterator it = list.listIterator();
while(it.hasNext())
{
Object obj = it.next();//ConcurrentModificationException
if(obj.equals("abc2"))
{
//list.add("abc9");
//it.add("abc9");//通过列表迭代器对象,在迭代器过程中,对集合的元素进行添加。
it.set("abc7777");//替换abc2元素
}
}
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);
}
}
LinkedList
特有方法:
addLast();
addFirst();
在jdk1.6时,
offerFirst()
offerLast()
getLast();返回元素,并不移除。如果集合中没有元素。会出现List list = new ArrayList();
//添加要演示的元素。
list.add("abc1");
list.add("abc2");
list.add("abc3");
sop("原集合 :"+list);
//插入。
list.add(1,"abc9");//如果角标不存在。会出现IndexOutOfBoundsException
getFirst();
jdk1.6
peekFirst() 返回元素,并不移除。如果集合中没有元素。返回null
peekLast()
removeLast();移除并返回被移除的元素。如果集合中没有元素。会出现NoSuchElementException
removeFirst();
jdk1.6
pollFirst() :移除并返回被移除的元素。如果集合中没有元素,返回null
pollLast()
import java.util.*;
class LinkedListDemo
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();
link.addFirst("abc1");
link.addFirst("abc2");
link.addFirst("abc3");
link.addFirst("abc4");
link.clear();
System.out.println(link.getFirst());//NoSuchElementException
System.out.println(link);
while(!link.isEmpty())
{
System.out.println(link.removeFirst());
}
}
}