您的位置:首页 > 编程语言 > Java开发

Java基础--集合框架<一>

2013-06-08 20:13 218 查看


集合框架概述
在java中任何事物都是对象的,集合框架也是一种类。数据结构定义的类保存在集合框架中,所以也称为集合类,它们都在util包下。使用集合框架可以保存数据,和数组有很多相似的地方,可以把它看做一种“容器”。但是集合和数组还是有很大区别的,在数组定义时必须定义数组的大小,从而给数组对象分配内存。在定义集合时,并不需要定义集合大小的,系统会自动给集合设置一个大小。

Java中集合类关系图:





Collection

|--List:元素是有序的,元素可以重复。因为该集合体系有索引。

|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。

|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。

|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。

|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。

|--TreeSet:可以对Set集合中的元素进行排序。底层数据结构是二叉树。



Collection

Collection层次结构中的根接口,Collection定义了集合框架的共性功能。

集合的作用是用来保存数据,所以集合接口中包含了对数据的增删改查等基本功能。

1,添加:

add(object):添加一个元素

addAll(Collection):添加一个集合中的所有元素。

2,删除:

clear():将集合中的元素全删除,清空集合。

remove(obj):删除集合中指定的对象。注意:删除成功,集合的长度会改变。

removeAll(collection):删除部分元素。部分元素和传入Collection一致。

3,判断:

booleancontains(obj):集合中是否包含指定元素。

booleancontainsAll(Collection):集合中是否包含指定的多个元素。

booleanisEmpty():集合中是否有元素。

4,获取:

intsize():集合中有几个元素。

5,取交集:

booleanretainAll(Collection):对当前集合中保留和指定集合中的相同的元素。如果两个集合元素相同,返回flase;如果retainAll修改了当前集合,返回true。

6,获取集合中所有元素:

Iteratoriterator():迭代器

7,将集合变成数组:

toArray();

List列表接口

List列表接口又叫做有序集合接口,在List接口中每一个数据都有一个索引相对应。List接口继承了Collection集合接口,所以具备了collection接口中的所有方法。
List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。

|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。

|--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。

|--Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。

整理了List特有方法。凡是可以操作角标的方法都是该体系特有的方法

1,添加:

add(index,element):在指定的索引位插入元素。

addAll(index,collection):在指定的索引位插入一堆元素。

2,删除:

remove(index):删除指定索引位的元素。返回被删的元素。

3,获取:

Objectget(index):通过索引获取指定元素。

intindexOf(obj):获取指定元素第一次出现的索引位,如果该元素不存在返回-1;

所以,通过-1,可以判断一个元素是否存在。

intlastIndexOf(Objecto):反向索引指定元素的位置。

ListsubList(start,end):获取子列表。

4,修改:

Objectset(index,element):对指定索引位进行元素的修改。

5,获取所有元素:

ListIteratorlistIterator():list集合特有的迭代器。

List集合支持对元素的增、删、改、查。

List集合因为角标有了自己的获取元素的方式:遍历。

for(intx=0;x<list.size();x++){

sop("get:"+list.get(x));

}

在进行list列表元素迭代的时候,如果想要在迭代过程中,想要对元素进行操作的时候,比如满足条件添加新元素。会发生.ConcurrentModificationException并发修改异常。

导致的原因是:

集合引用和迭代器引用在同时操作元素,通过集合获取到对应的迭代器后,在迭代中,进行集合引用的元素添加,迭代器并不知道,所以会出现异常情况。

如何解决呢?

既然是在迭代中对元素进行操作,找迭代器的方法最为合适.可是Iterator中只有hasNext,next,remove方法.通过查阅的它的子接口,ListIterator,发现该列表迭代器接口具备了对元素的增、删、改、查的动作。

ListIterator是List集合特有的迭代器。

ListIteratorit=list.listIterator;//取代Iteratorit=list.iterator;

ArrayList类

ArrayList数组列表类,它和数组相似,但ArrayList的大小是可以改变的。ArrayList类实现了List接口中增删改查的方法。
下面通过代码演示ArrayList的具体用法:

importjava.util.ArrayList;
importjava.util.Iterator;
importjava.util.ListIterator;
publicclassArrayListDemo{
	publicstaticvoidmain(String[]args)
	{
		ArrayListal=newArrayList();//新建一个ArrayList对象
		al.add("张三");	//调用添加方法add添加一条数据
		al.add("李四");
		al.add("王五");		
		al.add("李四");		//ArrayList对象中元素是可以重复的
		
		//al.remove(2);//删除指定索引位的元素并返回被删的元素"李四"。
		
		al.get(1);	//通过索引获取指定元素"张三"
		al.indexOf("张三");//获取指定元素第一次出现的索引位,如果该元素不存在返回-1
		al.lastIndexOf("张三");//反向索引指定元素的位置
		al.subList(0,2);	//获取子列表(角标为0~2:但不包括2)
		
		al.set(0,"老刘");	//对指定索引位进行元素的修改
		
		Iteratorit=al.iterator();//创建迭代器对象
		while(it.hasNext())	//判断:如果存在内容,遍历
		{
			System.out.println(it.next());//打印
		}
		
		//list集合特有的迭代器ListIteratorlistIterator()
		ListIteratoriterator=al.listIterator();//通过调用listIterator()创建迭代器对象
		while(iterator.hasNext())
		{
			Objectobj=iterator.next();
			if(obj.equals("java02"))
			{
				//在迭代时,不可以通过集合对象的方法操作集合中的元素。
				//al.add("java009");×错误用法
				
				//必须通过迭代器操作集合中元素
				iterator.add("老王");				
			}			
		}		
	}
}



LinkedList链状列表
在LinkedList中,所有元素是以链状的形式存在。相邻的几个数据组成一个链,具体数量和链的多少都是有系统自动分配的,不受程序员控制。

特点:当查找某一个数据时需要首先找到它所在的链,然后在该链中再查找数据,所以LinkedList
的查找效率低于ArrayList。

下面通过代码演示LinkList的具体用法:

importjava.util.*;
publicclassLinkList{
	publicstaticvoidmain(String[]args)
	{
		LinkedListlink=newLinkedList();//创建LinkedList对象
		link.add("java1.0");//向LinkedList对象中添加元素
		link.add("java2.0");
		link.add("java3.0");
		link.add("java3.0");//可以添加相同元素
		sop(link);
		
		link.addFirst("C++");		//将指定元素插入此列表的开头
		link.offerFirst("带头大哥");	//在JDK1.6中的替代方法:在此列表的开头插入指定的元素
		sop(link);

		link.addFirst("addFirst起始");		//将指定元素插入此列表的末尾
		link.offerFirst("offerFirst末尾");		//在JDK1.6中的替代方法:将指定元素插入此列表的末尾
		/*
		link.get(0);	//获得返回此列表中指定位置处的元素
		link.removeFirst();//取出第一个,其他元素删除
		link.removeLast();	//取出第一个,其他元素删除
		*/
		link.peekFirst();//获取但不移除此列表的第一个元素;如果此列表为空,则返回null。
		link.peekLast();//获取元素,但不删除元素。如果集合中没有元素,会返回null。
		link.pollFirst();//获取并移除此列表的第一个元素;如果此列表为空,则返回null。
		link.pollLast();//获取元素,但是元素被删除。如果集合中没有元素,会返回null。

		sop(link);
		sop(link.peekFirst());
		sop(link.size());

//		sop(link.getFirst());
//		sop(link.getLast());
//		while(!link.isEmpty()){
//			sop(link.removeLast());
//		}
//		sop(link.removeFirst());
//		sop(link.removeFirst());
//		sop(link.removeFirst());
//		sop(link.removeFirst());
//		sop(link);
//		sop(link.size());
	}
	publicstaticvoidsop(Objectobj){
		System.out.println(obj);
	}
}


迭代器

迭代是取出集合元素的一种方式,因为Collection类中有iterator方法,所以每一个子类集合对象都具备迭代器。

importjava.util.ArrayList;
importjava.util.ListIterator;
importjava.util.*;
/*
List集合特有的迭代器。ListIterator是Iterator的子接口。

在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。

所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,
只能对元素进行判断,取出,删除的操作,
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。

该接口只能通过List集合的listIterator方法获取。
注意:迭代器的next方法返回的是Object类型,所以要记得类型装换
*/
publicclassIterator{
	publicstaticvoidmain(String[]args)
	{
		//演示列表迭代器
		ArrayListal=newArrayList();
		al.add("java01");//add(Objectobj);
		al.add("java02");
		al.add("java03");
		al.add("java04");		
		
		ListIteratorli=al.listIterator();
			
		//list集合特有的迭代器ListIterator
		while(li.hasNext())
		{
			Objectobj=li.next();//迭代器的next方法返回的是Object类型
			if(obj.equals("java02"))
			{//在迭代时,不可以通过集合对象的方法操作集合中的元素。
				//al.add("java009");×错误用法
				
				li.add("替换后的java02");
				
//用指定元素替换next或previous返回的最后一个元素(可选操作)。				
//				li.set("java006");
			}
		}
		
		while(li.hasPrevious())
		{//使用列表迭代器逆向遍历列表,有多个元素
			sop("hasPrevious---"+li.previous());			
		}
		//sop("hasNext---"+li.hasNext());
		//sop("hasPrevious---"+li.hasPrevious());
		
		sop(al);//输出al
		
		/*普通迭代
		//在迭代过程中,准备添加或删除元素
		Iteratorit=al.iterator();
		while(it.hasNext())
		{
			Objectobj=it.next();
			if(obj.equals("java02"))
				//al.add("java08");//当方法检测到对象的并发修改,但不允许这种修改时,抛出异常。
				it.remove();//将"java02"的引用从集合中删除了
			sop("obj="+obj);	
		}
		sop("al="+al);
		*/
	}
	
	publicstaticvoidsop(Objectobj){
		System.out.println(obj);
	}	
}



|--Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。

|--HashSet:底层数据结构是哈希表。是线程不安全的。不同步。

HashSet是如何保证元素唯一性的呢?

是通过元素的两个方法,hashCode和equals来完成。

如果元素的HashCode值相同,才会判断equals是否为true。

如果元素的hashcode值不同,不会调用equals。

注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。

|--TreeSet:可以对Set集合中的元素进行排序。

底层数据结构是二叉树。

保证元素唯一性的依据:compareTo方法return0.

TreeSet排序的第一种方式:让元素自身具备比较性。

元素需要实现Comparable接口,覆盖compareTo方法。

也种方式也成为元素的自然顺序,或者叫做默认顺序。

TreeSet的第二种排序方式。

当元素自身不具备比较性时,或者具备的比较性不是所需要的。

这时就需要让集合自身具备比较性。

在集合初始化时,就有了比较方式。

hashset的应用

publicclassHashSetDemo{
	publicstaticvoidsop(Objectobj)
	{
		System.out.println(obj);
	}
	publicstaticvoidmain(String[]args)
	{
		HashSeths=newHashSet();
		sop(hs.add("java03"));
		sop(hs.add("java03"));//无法添加重复false
		hs.add("java01");
		hs.add("java02");
				
		hs.add("java04");
		Iteratorit=hs.iterator();
		while(it.hasNext())
		{
			sop(it.next());
		}		
	}
}
importjava.util.HashSet;

/*
往hashSet集合中存入自定对象
姓名和年龄相同为同一个人,重复元素。

HashSet是如何保证元素唯一性的呢?
			是通过元素的两个方法,hashCode和equals来完成。
			如果元素的HashCode值相同,才会判断equals是否为true。
			如果元素的hashcode值不同,不会调用equals。

*/

classPerson2
{
	privateintage;
	privateStringname;
	publicPerson2(Stringname,intage)
	{
		this.name=name;
		this.age=age;
	}
	publicStringgetName()
	{
		returnname;
	}
	publicintgetAge()
	{
		returnage;
	}	
	
	publicinthashCode()
	{//覆盖父类中的hashCode方法
		System.out.println(this.name+"...hashCode");
//		return60;
		returnname.hashCode()+age*11;//避免重复
	}
	
	//覆盖父类中的equals方法
	publicbooleanequals(Objectobj)
	{
		if(!(objinstanceofPerson2))
			returnfalse;		
		Person2p=(Person2)obj;	
		
		System.out.println(this.name+"--equals--"+p.name);
		returnthis.name.equals(p.name)&&this.age==p.age;
	}
}
publicclassHashsetTest{
	publicstaticvoidsop(Objectobj)
	{
		System.out.println(obj);
	}
	publicstaticvoidmain(String[]args)
	{
		HashSeths=newHashSet();
		hs.add(newPerson2("a1",11));
		hs.add(newPerson2("a2",12));
		hs.add(newPerson2("a3",22));
//		hs.add(newPerson2("a2",12));
//		hs.add(newPerson2("a3",22));
		
		//sop("a1:"+hs.contains(newPerson2("a1",11)));
		
		sop(hs.remove(newPerson2("a2",12)));
		
//		Iteratorit2=hs.iterator();
//		while(it2.hasNext())
//		{
//			Person2p=(Person2)it2.next();
//			sop(p.getName()+"-"+p.getAge());
//		}		
	}
}


TreeSet

importjava.util.*;
/*
当元素自身不具备比较性,或者具备的比较性不是所需要的。
这时需要让容器自身具备比较性。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

当两种排序都存在时,以比较器为主。

定义一个类,实现Comparator接口,覆盖compare方法。

*/
classStudent2implementsComparable//该接口强制让学生具备比较性
{
	privateStringname;
	privateintage;
	Student2(Stringname,intage)
	{
		this.name=name;
		this.age=age;
	}
	publicStringgetName(){
		returnname;
	}
	publicintgetAge(){
		returnage;
	}
	
	@Override
	publicintcompareTo(Objecto)
	{
		//返回负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
		
		if(!(oinstanceofStudent2))
			thrownewRuntimeException("不是学生对象");
		Student2s=(Student2)o;
		System.out.println(this.name+"..compare.."+s.name);
		
		if(this.age>s.age)
			return1;
		if(this.age==s.age)
		{
			returnthis.name.compareTo(s.name);
		}			
		return-1;
	}	
}

publicclassTreeSetDemo2{
	publicstaticvoidsop(Objectobj)
	{
		System.out.println(obj);
	}
	publicstaticvoidmain(String[]args)
	{
		TreeSetts=newTreeSet();//接收了一个接口子对象
		//必须具备比较性
		ts.add(newStudent2("lisi01",22));
		ts.add(newStudent2("lisi02",21));
		ts.add(newStudent2("lisi97",19));
		ts.add(newStudent2("lisi97",17));
		ts.add(newStudent2("lisi03",20));
		
		Iteratorit=ts.iterator();
		while(it.hasNext())
		{
			Student2s=(Student2)it.next();
			sop(s.getName()+"---"+s.getAge());
		}
	}
}

//定义比较器,实现Comparator接口,覆盖compare方法。
classMyCompareimplementsComparator
{
	@Override
	publicintcompare(Objecto1,Objecto2)
	{
		Student2s1=(Student2)o1;
		Student2s2=(Student2)o2;
		intnum=s1.getName().compareTo(s2.getName());
		if(num==0)
		{	
			newInteger(s1.getAge()).compareTo(newInteger(s2.getAge()));
			/*
			if(s1.getAge()>s2.getAge())
				return1;
			if(s1.getAge()<s2.getAge())
				return-1;
			return0;
			*/
		}
		returnnum;
	}	
}







                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: