您的位置:首页 > 职场人生

黑马程序员——集合框架(单列集合:Collection接口)

2015-09-02 14:30 956 查看

------- android培训java培训、期待与您交流!
----------



单列集合体系结构图
注:图中列出了程序中常用的单列集合类,其中,虚线框里都是接口类型,而实线框里是具体的实现类。

为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象操作,就对对象进行存储,集合就是存储对象常用的一种方式。而每一个容器对数据的存储方式都有不同,这种存储数据的方式称之为数据结构。

数组和集合类同时容器,有何不同?
数组虽然也可以存储对象,但长度是固定的,集合的长度是可变的;数组中可以存储基本数据类型,集合只能存储对象。

集合类的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

一、Collection接口

Collection接口的常用方法:

boolean add(Object o)

向集合中添加一个元素

boolean addAll(Collection c)

将指定Collection中的所有元素添加到该集合中

void clear()

删除该集合中的所有元素

boolean remove(Object o)

删除该集合中的指定元素

boolean removeAll(Collection c)

删除指定集合中的所有元素

boolean isEmpty()

判断该集合是否为空

boolean contains(Object o)

判断该集合中是否包含某个元素

boolean containsAll(Collection c)

判断该集合中是否包含指定集合中的所有元素

Iterator iterator()

返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合的所有元素

int size()

获取该集合的元素个数

演示:

import java.util.*;

class CollectionDemo

{

public staticvoid main(String[] args)

{ }

publicstatic void sop(Object obj)

{

System.out.println(obj);

}

public staticvoid base_method()

{

//创建一个集合容器,使用Collection接口的子类ArrayList

ArrayListal = new ArrayList();

//添加元素

al.add("java01");//add(Objectobj);

al.add("java02");

al.add("java03");

al.add("java04");

//打印集合

sop("打印原集合:"+al);

//删除元素。

//al.remove("java02");

//清空集合

//al.clear();

//判断元素

sop("java03是否存在:"+al.contains("java03"));

//获取个数,集合长度

sop("size:"+al.size());

sop(al);

}

public static void method_2()

{

ArrayListal1 = new ArrayList();

al1.add("java01");

al1.add("java02");

al1.add("java03");

al1.add("java04");

ArrayListal2 = new ArrayList();

al2.add("java01");

al2.add("java02");

al2.add("java05");

al2.add("java06");

//al1.retainAll(al2);//取交集,al1中只会保留和al2中相同的元素。

al1.removeAll(al2);//移除al1中和al2中相同的元素。

sop("al1:"+al1);

sop("al2:"+al2);

}

public staticvoid method_get()

{

//添加元素

al.add("java01");//add(Objectobj);

al.add("java02");

al.add("java03");

al.add("java04");

/*

Iterator it = new Iterator();//获取迭代器,用于取出集合中的元素。

while(it.hasNext())

{

sop(it.next());

}

*/

//节省内存,更优化。

for(Iteratorit = al.iterator(); it.hasNext(); )

{

sop(it.next());

}

}

}

Iterator(迭代器)

每个集合都要取出元素,就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。那么取出方式就被定义成了内部类。而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都有共性内容:判断和取出,那么就可以将其共性抽取(形成Iterator接口)那么这些内部类都符合一个规则。规则是Iterator。

如何获取集合的取出对象呢?通过一个对外提供的方法iterator();。

二、List接口

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

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

LinkedList:底层的数据结构是链表数据结构,特点:增删速度快,查询稍慢。

Vector:底层数据结构是数组,线程同步,被ArrayList代替了。

List接口的常用方法:

void add(int index,Object element)

将元素element插入在List集合的index处

boolean addAll(int index,Collection c)

将集合c所包含的所有元素插入到List集合的index处

Object get(int index)

返回集合索引index处的元素

Object remove(int index)

删除index索引处的元素

Object set(int index,Object element)

将索引index处元素替换成element对象,并将替换后的元素返回

int indexOf(Object o)

返回对象o在List集合中出现的位置索引

int lastIndex(Object o)

返回对象o在List集合中最后一次出现的位置索引

List subList(int fromIndex,int toIndex)

返回从索引fromIndex(包括)到toIndex(不包括)处所有元素集合组成的子集合。

案例:

import java.util.*;

class ListDemo

{

public staticvoid sop(Object obj)

{

System.out.println(obj);

}

public staticvoid method()

{

ArrayListal = new ArrayList();

//添加元素

al.add("java01");

al.add("java02");

al.add("java03");

sop("原集合是:"+al);

//在角标1位置添加元素。

al.add(1,"java09");

//删除指定位置的元素

//al.remove(2);

//修改元素

//al.set(2,"java007");

//通过角标获取元素

sop("get(1):"+al.get(1));

sop(al);

//获取所有元素

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

{

sop("al("+x+")="+al.get(x));

}

//迭代器获取

for(Iteratorit = al.iterator(); it.hasNext(); )

{

sop("next:"+it.next());

}

//通过indexOf获取对象的位置。

sop("index="+al.indexOf("java02"));

List sub= al.subList(1,3);

sop("sub="+sub);

}

public staticvoid main(String[] args)

{

//演示列表迭代器

ArrayListal = new ArrayList();

//添加元素

al.add("java01");

al.add("java02");

al.add("java03");

sop(al);

ListIteratorli = al.listIterator();

sop("hasNext():"+li.hasNext());

while(li.hasNext())

{

Objectobj = li.next();

if(obj.equals("java02"))

//li.add("java009");

li.set("java006");

}

while(li.hasPrevious())

{

sop("pre:"+li.previous());

}

sop("hasNext():"+li.hasNext());

sop("hasPrevious():"+li.hasPrevious());

sop(al);

/*

//在迭代过程中,准备添加或者删除元素

for(Iteratorit = al.iterator(); it.hasNext(); )

{

Objectobj = it.next();

if(obj.equals("java02"))

//al.add("java008");//发生异常

it.remove();//将java02的引用从集合中删除了。

sop("obj="+obj);//java02正在被obj使用,所以能够打印出来。

}

sop(al);

*/

}

}

ListIterator:

List集合特有的迭代器,ListIterator是Iterator的子接口。在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作,如:添加,修改等,就需要使用其子接口,ListIterator。该接口中能通过List集合的ListIterator方法获取。

LinkedList特有方法:

addFirst();//在第一个位置上添加元素

addLast();//在最后一个位置上添加元素

getFirst();//获取第一个元素

getLast();//获取最后一个元素

获取元素,但不删除元素。如果集合中没有元素,会抛出NoSuchElementException异常

removeFirst();//获取删除第一个元素

removeLast();//获取删除最后一个元素

获取元素,但是元素被删除,如果集合中没有元素,获取元素,但不删除元素。如果集合中没有元素,会抛出NoSuchElementException异常

在JDK1.6出现了替代方法

offerFirst();

offerLast();

添加

peekFirst();

peekLast();

获取元素,但不删除元素。如果集合中没有元素,则返回null

pollFirst();

pollLast();

获取元素,但是元素被删除。如果集合中没有元素,则返回null

*/

例子:

import java.util.*;

class LinkedListDemo

{

public static void sop(Objectobj)

{

System.out.println(obj);

}

public static void main(String[]args)

{

LinkedList link = new LinkedList();

link.addLast("java01");

link.addLast("java02");

link.addLast("java03");

link.addLast("java04");

/*

sop(link);

sop(link.getFirst());//java01

sop(link.getFirst());//java01

sop(link.getLast());//java04

sop(link.removeFirst());java01

sop(link.removeFirst());java02

sop("size="+link.size());

*/

while(!link.isEmpty())

{

sop(link.removeLast());

}

}

}

枚举:
JDK中提供了一个Vector集合,用法与ArrayList完全相同,区别在于Vector集合是线程安全的,而ArrayList集合是线程不安全的。在Vector类中提供了一个element()方法用于返回Enumeration对象,通过Enumeration对象就可以遍历集合中的元素。

其实枚举和迭代器是一样的,因为名称过长以及方法名过长,所以被迭代器取代了。

import java.util.*;

public class VectorDemo

{

publicstatic void main(String[] args)

{

Vectorv = new Vector();/ //创建Vector对象

v.add(“Jack”); //向Vector对象中添加元素

v.add(“Rose”);

v.add(“Tom”);

Enumerationen = v.elements(); //获得Enumeration对象

while(en.hasMoreElement()) //判断该对象是否有更多元素

{

Objectobj = en.nextElement(); //取出该对象的下一个元素

System.out.println(obj);

}

}

}

三、Set集合

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

|--HashSet:底层数据结构是哈希表。

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

是通过元素的两个方法,hashCode和equals来完成的,如果元素的HashCode值相同,才会判断equals

是否为true。如果元素的HashCode值不同,不会调用equals。

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

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

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

TreeSet排序的第一种方式:

让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。

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

TreeSet的第二种排序方式:

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

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

Set集合的功能和Collection是一致的。

需求:

往TreeSet集合中存储自定义对象学生,

想按照学生的年龄进行排序。

记住:

排序时,当主要条件相同时,一定要判断一下次要条件。

*/

class TreeSetDemo

{

public staticvoid main(String[] args)

{

TreeSetts = new TreeSet();

//TreeSet集合能排序,但是它不知道按什么排序,学生对象不具备比较性,

//在存储时就会出错,必须要让元素具备比较性,怎么具备比较性呢?

//实现Comparable接口,重写compareTo方法(比较对象与指定对象顺序)

ts.add(new Student("lisi02",22));

ts.add(new Student("lisi007",20));

ts.add(newStudent("lisi09",19));

//年龄相同,按姓名排序

ts.add(newStudent("lisi08",19));

//ts.add(newStudent("lisi007",20));//重复元素存不进来。

Iteratorit = ts.iterator();

while(it.hasNext())

{

Studentstu = (Student)it.next();

System.out.println(stu.getName()+"..."+stu.getAge());

}

}

}

class Student implements Comparable//该接口强制让学生具备比较性。

{

privateString name;

private intage;

Student(Stringname,int age)

{

this.name= name;

this.age= age;

}

public intcompareTo(Object obj)//覆盖Comparable中compareTo方法。

{

if(!(objinstanceof Student))//判断obj对象是否属于Student

throw new RuntimeException("不是学生对象");//不属于学生对象抛出异常,此异常不能再方法上声明,因为是覆盖的方法。

Student s = (Student)obj;

System.out.println(this.name+"...compareTo..."+s.name);

//正整数、零或负整数,根据此对象是大于、等于还是小于指定对象。

if(this.age>s.age)

return1;

if(this.age==s.age)//判断完年龄(主要条件相同),再判断姓名(次要条件)

returnthis.name.compareTo(s.name);//字符串具备比较性,String类本身就实现了Comparable接口

return-1;

}

public StringgetName()

{

returnname;

}

public intgetAge()

{

returnage;

}

}

importjava.util.*;

/*

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

这是需要让容器自身具备比较性。

定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

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

怎么定义比较器?

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

*/

class Student implements Comparable//该接口强制让学生具备比较性。

{

private String name;

private int age;

Student(String name,int age)

{

this.name = name;

this.age = age;

}

public int compareTo(Objectobj)//覆盖Comparable中compareTo方法。

{

if(!(obj instanceofStudent))//判断obj对象是否属于Student

throw newRuntimeException("不是学生对象");//不属于学生对象抛出异常,此异常不能再方法上声明,因为是覆盖的方法。

Student s = (Student)obj;

System.out.println(this.name+"...compareTo..."+s.name);

//正整数、零或负整数,根据此对象是大于、等于还是小于指定对象。

if(this.age>s.age)

return 1;

if(this.age==s.age)//判断完年龄(主要条件相同),再判断姓名(次要条件)

return this.name.compareTo(s.name);//字符串具备比较性,String类本身就实现了Comparable接口

return -1;

}

public String getName()

{

return name;

}

public int getAge()

{

return age;

}

}

class
TreeSetDemo2

{

public static void main(String[]args)

{

TreeSet ts = new TreeSet(newMyCompare());

//TreeSet集合能排序,但是它不知道按什么排序,学生对象不具备比较性,

//在存储时就会出错,必须要让元素具备比较性,怎么具备比较性呢?

//实现Comparable接口,重写compareTo方法(比较对象与指定对象顺序)

ts.add(newStudent("lisi02",22));

ts.add(newStudent("lisi02",21));

ts.add(new Student("lisi007",20));

ts.add(newStudent("lisi09",19));

//年龄相同,按姓名排序

ts.add(newStudent("lisi08",19));

//ts.add(newStudent("lisi007",20));//重复元素存不进来。

Iterator it = ts.iterator();

while(it.hasNext())

{

Student stu =(Student)it.next();

System.out.println(stu.getName()+"..."+stu.getAge());

}

}

}

//定义一个比较器实现Comparator,覆盖Compare方法

class MyCompare implements Comparator

{

public int compare(Objecto1,Object o2)

{

Student s1 = (Student)o1;

Student s2 = (Student)o2;

int num =s1.getName().compareTo(s2.getName());

if(num==0)

{

return newInteger(s1.getAge()).compareTo(new Integer(s2.getAge()));

/*

if(s1.getAge()>s2.getAge())

return 1;

if(s1.getAge()==s2.getAge())

return 0;

return-1;

*/

}

returnnum;

}

}


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