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

黑马程序员-java 集合框架

2014-12-03 08:42 295 查看
---------- android培训java培训、java学习型技术博客、期待与您交流! ---------

一、基本概念

集合类:java中的集合类就像一个容器,专门用来存储Java类的对象。

前面我们学过,数组也可以储存对象,但在一下情况不适应需求,一是对象元素的种类不一致时;二是当对象元素的数量可变或不确定时。为了保存数量和种类可变的对象元素,jdk中提供了一系列特殊的类,这些类可以存储任意类型对象,并且长度可变,统称为集合。

集合类位于java.util包中,使用时一定要注意导包。

集合按照存储结构,分为两大部分,即单列集合Collection和双列集合Map。

*Collection:单列集合根接口,用于储存一些列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。其中List的特点是元素有序,元素可重复。set的特点是元素无序且不可重复。这里说的有序无序,主要是指存入顺序和取出顺序是否一致。

*Map:双列集合类根接口,用于存储具有键、值映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的键找到对应的值。集合的基本继承体系结构如下:



二、Collection基本功能

Collection定义了集合框架的共性功能:

1,添加

add(e);

addAll(collection);

2,删除

remove(e);

removeAll(collection);

clear();清空整个集合。

3,判断。

contains(e);

isEmpty();

4,获取

iterator();迭代器

size();

5,获取交集。

retainAll();

6,集合变数组。

toArray();

有一点需要特别说明的是,集合中存储的是对象的引用,即地址。

关于迭代器Iterator的说明:

其实就是集合的取出元素的方式。

如同抓娃娃游戏机中的夹子。

迭代器是取出方式,会直接访问集合中的元素。

所以将迭代器通过内部类的形式来进行描述。

通过容器的iterator()方法获取该内部类的对象。

迭代器中的方法:

boolean hasNext()  如果仍有元素可以迭代,则返回 true。

next()  返回迭代的下一个元素。
void remove()  从迭代器指向的 collection 中移除迭代器返回的最后一个元素。

[/code]
迭代器Iterator()使用例子:[code]Iterator it = arraylist.iterator();//获取迭代器,用于取出集合中的元素。

while(it.hasNext())
{

System.out.println(arraylist.next());

}
或使用for循环:

for(Iterator it = arraylist.iterator(); it.hasNext() ; )
{
System.out.println(arraylist.next());
}

三、Collection体系

[/code]Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。
[/code]
|--Set:元素是无序,元素不可以重复。

四、list集合

List: 特有方法。凡是可以操作角标的方法都是该体系特有的方法。 增 add(index,element); addAll(index,Collection); 删 remove(index); 改 set(index,element); 查 get(index): subList(from,to); listIterator(); int indexOf(obj):获取指定元素的位置。 ListIterator listIterator(); List集合特有的迭代器。ListIterator是Iterator的子接口。

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

LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。特有方法:1、增 addFirst(); addLast();2、获取 //获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementException getFirst(); getLast();3、删 //获取元素,并删除元素。如果集合中没有元素,会出现NoSuchElementException removeFirst(); removeLast();在JDK1.6以后,出现了替代方法。1、增 offFirst(); offLast();2、获取 //获取元素,但是不删除。如果集合中没有元素,会返回null。 peekFirst(); peekLast();3、删 //获取元素,并删除元素。如果集合中没有元素,会返回null。 pollFirst(); pollLast();

LinkedList 练习

linkedList练习

需求:使用LinkedList模拟一个堆栈或者队列数据结构。

基本数据概念:

堆栈:先进后出 如同一个杯子。

队列:先进先出 First in First out FIFO 如同一个水管。

队列数据结构:

import java.util.*;
public class TextDL
{
public static void main(String[] args)
{
DuiLi d = new DuiLi();
d.myAdd("java01");
d.myAdd("java02");
d.myAdd("java03");
d.myAdd("java04");
while(d.myEmpty()!=true)
{
System.out.println(d.myGet());
}
}
}

class DuiLi
{
private LinkedList link;//私有化一个ListedList对象的引用,以便于在类的其它地方进行引用。
DuiLi()//建立一个空参数的构造函数,初始化一个ListList对象。
{
link= new LinkedList();
}
public void myAdd(Object obj)//添加元素方法封装
{
link.addFirst(obj);
}
public Object myGet()//获取元素方法封装
{
return link.removeLast();
}
public boolean myEmpty()//判断集合是否为空
{
return link.isEmpty();
}
}


堆栈数据结构:

import java.util.*;
class TestDZ
{
public static void main(String[] args)
{
DuiLi dz = new DuiLi();
dz.myAdd("java01");
dz.myAdd("java02");
dz.myAdd("java03");
dz.myAdd("java04");
while(dz.myEmpty()!=true)
{
System.out.println(dz.myGet());
}
}
}

class DuiLi
{
private LinkedList link;//私有化一个ListedList对象的引用,以便于在类的其它地方进行引用。
DuiLi()//建立一个空参数的构造函数,初始化一个ListList对象。
{
link= new LinkedList();
}
public void myAdd(Object obj)//添加元素方法封装
{
link.addFirst(obj);
}
public Object myGet()//获取元素方法封装
{
return link.removeFirst();//获取第一个元素,也就是最后一个放进去了。
}
public boolean myEmpty()//判断集合是否为空
{
return link.isEmpty();
}
}


两种数据结构,在设计时主要需要注意的是,存入方式和取出方式的对应关系。

ArrayList练习

练习一:去除ArrayList集合中的重复元素。

import java.util.*;
public class Demo8
{
public static void main(String[] args)
{
ArrayList al=new ArrayList();
al.add("java01");
al.add("java02");
al.add("java01");
al.add("java02");
al.add("java04");
al.add("java03");
al.add("java04");
System.out.println(al);
al=OSame(al);
System.out.println(al);
}
public static ArrayList  OSame(ArrayList al)
{
//定义一个新的集合,来装备选集合中元素
//再取出过程中判断新集合中是否包含取出的元素
//最后返回新集合
ArrayList newAl = new ArrayList();
ListIterator it = al.listIterator();
while (it.hasNext())
{
//定义一个Object类型的引用来接收取出的元素
Object obj=it.next();
if (!newAl.contains(obj))
{
newAl.add(obj);
}
}
return newAl;
}
}


练习2

/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素.

比如:存入人对象.同姓名 同年龄,视为一个人,为重复元素.

思路:
1.对人描述,将数据封装进人对象.
2.定义容器,将人存入.
3.取出.

List集合判断元素是否相同,依据是元素的equals方法,contains方法调用了equals方法,
remove也调用了equals方法.
*/
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//复写了equals方法,被contains方法调用
public boolean equals(Object obj)
{
if (!(obj instanceof Person))
{
return false;
}
Person p = (Person)obj;
System.out.println(this.name+"---"+p.name);
return this.name.equals(p.name)&&this.age==p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class  ArrayListTest2
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("2B",15));
al.add(new Person("2A",30));
al.add(new Person("2B",15));
al.add(new Person("3C",50));
al.add(new Person("4D",60));
al.add(new Person("3C",50));

ArrayList al1 = getSingleElement(al);

Iterator it = al1.iterator();
while (it.hasNext())
{
//由于迭代器next()方法获取的元素是Object类型的,
//所以需要向下转型为Person
Person p = (Person)it.next();
sop(p.getName()+"-------"+p.getAge());
}

}

public static ArrayList getSingleElement(ArrayList al)
{
ArrayList newal = new ArrayList();
ListIterator li = al.listIterator();
while (li.hasNext())
{
Object obj = li.next();
if (!(newal.contains(obj)))//contain方法调用了底层的equals方法
{
newal.add(obj);
}
}
return newal;
}
}


五、Set集合

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

|--HashSet:底层数据结构是哈希表。线程不同步。 保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true。

|--TreeSet:可以对Set集合中的元素进行排序。默认按照字母的自然排序。底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return
0。

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

HasSet

HashSet:线程不安全,存取速度快。

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

注意:HashSet对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法,所以在构建类的时候要复写hashCode()方法和equals方法,以便在对象使用过程中的完整性。

示例:

往hashSet集合中存入自定对象。

姓名和年龄相同为同一个人,重复元素。

import java.util.*;
class Demo9
{
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new Person("JAVA1",20));
hs.add(new Person("JAVA2",40));
hs.add(new Person("JAVA3",30));
hs.add(new Person("JAVA2",60));
hs.add(new Person("JAVA1",20));
Iterator it = hs.iterator();
while (it.hasNext())
{
Person p = (Person)it.next();//因为add()方法中接受的是Object类型,
//属于多态的父类引用指向子类对象,因为要使用子类特有方法,所以要强转。
System.out.println("...."+p.getAge()+"..."+p.getName());
}
}
}
/*
定义一个Person类,两个成员变量,两个获取成员变量的方法。
以年龄和姓名同时相等判定为同一个人。
在定义一个类的时候,为了方便与操作(在集合中存储,尤其是在HashSet集合中,
要重写属于本类的特有equals()方法和hashCode()方法,以便于元素唯一性的判定
在重写hashCode()方法时要依据判定元素是否相等的条件来生成独特的hashCode()方法
尽可能的生成独特的hashCode,减少对equals方法的调用,提高程序的运行效率。
在重写equals方法时,主要根据判定条件来重写equals方法。
*/
class Person
{
private String name;
private int age;
//定义一个构造函数。
Person(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public boolean equals(Object obj)  //参数列表一定要是Object类型
{
if(!(obj instanceof Person)) //判定对象是否属于Person类,否则没有强转的必要,会报错。
return false;
Person p=(Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}

public int hashCode()
{
return this.name.hashCode()+this.age;  //依据判定条件来确定hash值,并尽可能的确保其唯一性。
}

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