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


集合框架概述

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,判断:
boolean contains(obj) :集合中是否包含指定元素 。
boolean containsAll(Collection) :集合中是否包含指定的多个元素。
boolean isEmpty():集合中是否有元素。

4,获取:
int size():集合中有几个元素。

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

6,获取集合中所有元素:
Iterator  iterator():迭代器   

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,获取:

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

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

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

int lastIndexOf(Object o) :反向索引指定元素的位置。

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

4,修改:

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

5,获取所有元素:

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

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

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

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

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

}

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

导致的原因是:

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

如何解决呢?

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

ListIterator是List集合特有的迭代器

ListIterator it = list.listIterator;//取代Iterator it = list.iterator;

ArrayList

ArrayList数组列表类,它和数组相似,但ArrayList的大小是可以改变的。ArrayList类实现了List接口中增删改查的方法。

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class ArrayListDemo {
	public static void main(String[] args)
	{
		ArrayList al=new ArrayList(); //新建一个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, "老刘");	//对指定索引位进行元素的修改
		
		Iterator it=al.iterator(); //创建迭代器对象
		while(it.hasNext())	//判断:如果存在内容,遍历
		{
			System.out.println(it.next());  //打印
		}
		
		//list集合特有的迭代器 ListIterator listIterator()
		ListIterator iterator=al.listIterator();  //通过调用listIterator()创建迭代器对象
		while(iterator.hasNext())
		{
			Object obj=iterator.next();
			if(obj.equals("java02"))
			{
				//在迭代时,不可以通过集合对象的方法操作集合中的元素。
				//al.add("java009");  ×  错误用法
				
				//必须通过迭代器操作集合中元素
				iterator.add("老王");  				
			}			
		}		
	}
}

 

LinkedList  链状列表

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

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

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

import java.util.*;
public class LinkList {
	public static void main(String[] args)
	{
		LinkedList link =new LinkedList();  //创建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());
	}
	public static void sop(Object obj) {
		System.out.println(obj);
	}
}


 迭代器

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

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

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

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

该接口只能通过List集合的listIterator方法获取。
注意:迭代器的next方法返回的是Object类型,所以要记得类型装换
 */
public class Iterator {
	public static void main(String[] args)
	{
		//演示列表迭代器
		ArrayList al=new ArrayList();
		al.add("java01"); //add(Object obj);
		al.add("java02");
		al.add("java03");
		al.add("java04");		
		
		ListIterator li=al.listIterator();
			
		//list集合特有的迭代器 ListIterator
		while(li.hasNext())
		{
			Object obj=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
		
		/*普通迭代
		//在迭代过程中,准备添加或删除元素
		Iterator it=al.iterator();
		while(it.hasNext())
		{
			Object obj=it.next();
			if(obj.equals("java02"))
				//al.add("java08");//当方法检测到对象的并发修改,但不允许这种修改时,抛出异常。 
				it.remove(); //将"java02"的引用从集合中删除了
			sop("obj="+obj);	
		}
		sop("al="+al);
		*/
	}
	
	public static void sop(Object obj) {
		System.out.println(obj);
	}	
}

 


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

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

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

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

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

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

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

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

                           底层数据结构是二叉树。

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

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

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

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

                      TreeSet的第二种排序方式。

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

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

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

hashset的应用

public class HashSetDemo {
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args)
	{
		HashSet hs=new HashSet();
		sop(hs.add("java03"));
		sop(hs.add("java03"));  //无法添加重复  false
		hs.add("java01");
		hs.add("java02");
				
		hs.add("java04");
		Iterator it=hs.iterator();
		while(it.hasNext())
		{
			sop(it.next());
		}		
	}
}
import java.util.HashSet;

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

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

*/

class Person2
{
	private int age;
	private String name;
	public Person2(String name,int age) 
	{
		this.name=name;
		this.age=age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}	
	
	public int hashCode()
	{//覆盖父类中的hashCode方法
		System.out.println(this.name+"...hashCode");
//		return 60;
		return name.hashCode()+age*11;  //避免重复
	}
	
	//覆盖父类中的equals方法
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person2))
			return false;		 
		Person2 p=(Person2)obj;	
		
		System.out.println(this.name+"--equals--"+p.name);
		return this.name.equals(p.name)&&this.age==p.age;
	}
}
public class HashsetTest {
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args)
	{
		HashSet hs=new HashSet();
		hs.add(new Person2("a1", 11));
		hs.add(new Person2("a2", 12));
		hs.add(new Person2("a3", 22));
//		hs.add(new Person2("a2", 12));
//		hs.add(new Person2("a3", 22));
		
		//sop("a1:"+hs.contains(new Person2("a1", 11)));
		
		sop(hs.remove(new Person2("a2", 12)));
		
//		Iterator it2=hs.iterator();
//		while(it2.hasNext())
//		{
//			Person2 p=(Person2)it2.next();
//			sop(p.getName()+"-"+p.getAge());
//		}		
	}
}



TreeSet

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

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

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

*/
class Student2 implements Comparable  //该接口强制让学生具备比较性
{
	private String name;
	private int age;
	Student2(String name,int age)
	{
		this.name=name;
		this.age=age;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	
	@Override
	public int compareTo(Object o)
	{ 
		//返回负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
		
		if(!(o instanceof Student2))
			throw new RuntimeException("不是学生对象");
		Student2 s=(Student2)o;
		System.out.println(this.name+"..compare.."+s.name);
		
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);
		}			
		return -1;
	}	
}

public class TreeSetDemo2 {
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args)
	{
		TreeSet ts=new TreeSet(); //接收了一个接口子对象
		//必须具备比较性
		ts.add(new Student2("lisi01", 22));
		ts.add(new Student2("lisi02", 21));
		ts.add(new Student2("lisi97", 19));
		ts.add(new Student2("lisi97", 17));
		ts.add(new Student2("lisi03", 20));
		
		Iterator it=ts.iterator();
		while(it.hasNext())
		{
			Student2 s=(Student2)it.next();
			sop(s.getName()+"---"+s.getAge());
		}
	}
}

//定义比较器,实现Comparator接口,覆盖compare方法。
class MyCompare implements Comparator
{
	@Override
	public int compare(Object o1, Object o2) 
	{
		Student2 s1=(Student2)o1;
		Student2 s2=(Student2)o2;
		int num=s1.getName().compareTo(s2.getName());
		if(num==0)
		{	
			new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
			/*
			if(s1.getAge()>s2.getAge())
				return 1;
			if(s1.getAge()<s2.getAge())
				return -1;
			return 0;
			*/
		}
		return num;
	}	
}



 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值