1.用来存储对象的一种常见方式
2.集合的特点
(1)集合只用来存储对象
(2)集合的长度是可变的
(3)集合可以存储不同类型的对象
3.为什么会出现这么多的容器呢
因为每一个容器对数据的存储方式都不同,这个存储方式就称为数据结构
4.集合中存储的都是对象的引用(地址)
5.迭代器(通常用来遍历集合)
其实就是集合取出元素的方式
取出方式被定义成了内部类,定义在集合的内部,这样取出方式就可以直接访问集合中的元素,而每一个容器的数据结构不同,所以取出的动作细节也不一样,但是都有共性内容----判断和取出,那么就可以将共性抽取。这些内部类都符合一个规则,该规则就是Iterator。
如何获取集合的取出对象呢?
通过一个对外提供的方法iterator();
实例
import java.util.*;
class CollectionDemo
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add("java 01");
al.add("java 02");
al.add("java 03");
al.add("java 04");
for(Iterator it = al.iterator();it.hasNext();)
{
sop(it.next());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
6.集合框架
Collection
|--List:元素是有序的,元素可以重复,因为该集合体系中有索引
特有方法:凡是可以操作角标的方法都是该体系的特有方法
|--ArrayList:底层的数据结构是数组数据结构,特点是查询速度很快,但是
增删稍慢,线程不同步
|--LinkedList:底层使用的是链表数据结构,特点:增删速度很快,查询稍慢
|--Vector:底层是数组数据结构,线程同步。被ArrayList代替了
|--Set:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复
Set集合的功能和Collection是一致的,
|--HashSet:底层数据结构是哈希表,线程不同步
HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成的
如果元素的HashCode值相同,才会判断equals是否为true
如果元素的HashCode值不同,则不会判断equals。
|--TreeSet:可以对Set集合中的元素进行排序
底层结构是二叉树
保证元素唯一性的依据:compareTo方法return 0
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comoparable接口,覆盖compareTo方法
TreeSet排序的第二种方式:当元素自身不具备比较性,或者具备的
比较性不是所需要的。这时需要让容器自身具备比较性。定义了比
较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在的时候,以比较器为主
定义一个类,实现Comparator接口,覆盖compare方法,将该类对
象作为参数传递给TreeSet集合的构造器
注意:排序时,当主要条件相同时,一定要判断下次要条件
7.ListIterator是Iterator的子接口,是List集合特有的迭代器,在迭代的时候,不可以通过对象的方法操作集合中的元素,因为会发生ConcurrentModificationException并发修改异常,所以在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断、取出、删除的操作,如果想要进行其它的操作,如添加、修改等就需要使用其子接口ListIterator。该接口只能通过List集合的listIterator方法获取。
import java.util.*;
class CollectionDemo
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add("java 01");
al.add("java 02");
al.add("java 03");
al.add("java 04");
ListIterator li = al.listIterator();
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java 02"))
{
li.set("java 10"); //替换元素
//li.add("java 10"); //添加一个新的对象引用
}
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
8.枚举是vector特有的取出方式
枚举和迭代器很像,其实枚举和迭代是一样的,因为枚举的名称以及方法都过长,所以被迭代器取代了,枚举就郁郁而终了。
class VectorDemo
{
public static void main(String[] args)
{
Vector ve = new Vector();
ve.add("java 01");
ve.add("java 02");
ve.add("java 03");
ve.add("java 04");
Enumeration en = ve.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
}
9.LinkedList的特有方法
addFirst();
addLast();
//获取元素,但不删除元素,如果集合中没有元素,
//会出现NoSuchElementException异常
getFirst();
getLast();
//获取元素,但元素被删除。,如果集合中没有元素,
//会出现NoSuchElementException异常
removeFirst();
removeLast();
在JDK1.6出现了替代方法
offerFirst();
offerLast();
//获取元素,但不删除元素,如果集合中没有元素,
//会返回null
peekFirst();
peekLast();
//获取元素,但元素被删除。,如果集合中没有元素,
//会返回null
pollFirst();
pollLast();
10.用LinkedList模拟一个队列或堆栈的数据结构
import java.util.*;
class MyQueue
{
private LinkedList link;
MyQueue()
{
link = new LinkedList();
}
public void myAdd(Object obj)
{
link.addFirst(obj);
}
public Object myGet()
{
//return link.removeLast(); //模拟一个队列
return link.removeFirst(); //模拟一个堆栈
}
public boolean isNull()
{
return link.isEmpty();
}
}
class LinkedListDemo
{
public static void main(String[] args)
{
MyQueue myQueue = new MyQueue();
myQueue.myAdd("java 01");
myQueue.myAdd("java 02");
myQueue.myAdd("java 03");
myQueue.myAdd("java 04");
while(!myQueue.isNull())
{
System.out.println(myQueue.myGet());
}
}
}
11.去除ArrayList集合中的相同元素
import java.util.*;
class ArrayListDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add("java 01");
al.add("java 02");
al.add("java 01");
al.add("java 02");
al.add("java 03");
sop("原来" + al);
al = singleElement(al);
sop(al);
}
public static ArrayList singleElement(ArrayList al)
{
ArrayList newal = new ArrayList(); //创建一个新的ArrayList集合
Iterator it = al.iterator(); //使用迭代器遍历原集合
while(it.hasNext())
{
//注意在迭代循环时,next()调用一次,就需要用hasNext()判断一次
Object obj = it.next(); //使用迭代器遍历集合
if(!newal.contains(obj))
newal.add(obj);
}
return newal;
}
}
12.将自定义的对象存到ArrayList集合中,并去除相同元素
存人对象,同一姓名,同于元素的人视为同一个人
*/
import java.util.*;
class Person
{
private String name;
private int age;
//重写父类的equals方法
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj; //向下转型
return (p.name.equals(this.name) && p.age == this.age);
}
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class ArrayListDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("lisi01",35));
al.add(new Person("lisi02",32));
al.add(new Person("lisi02",32));
al.add(new Person("lisi04",39));
al.add(new Person("lisi04",39));
al = singleElement(al);
Iterator it = al.iterator();
while(it.hasNext())
{
//下面两个语句等同于 Person p = (Person)it.next();
Object obj = it.next();
Person p = (Person)obj; //向下转型
sop(p.getName() + "::" + p.getAge());
}
}
public static ArrayList singleElement(ArrayList al)
{
ArrayList newal = new ArrayList(); //创建一个新的ArrayList集合
Iterator it = al.iterator();
while(it.hasNext())
{
//注意在迭代循环时,next()调用一次,就需要用hasNext()判断一次
Object obj = it.next(); //使用迭代器遍历集合
//List集合判断元素是否相同,调用的是equals()方法
//下面调用的contains()方法底层调用的也是equals()方法
//所以需要在Person类中,重写根父类的equals()方法
if(!newal.contains(obj))
newal.add(obj);
}
return newal;
}
}
13. HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成的
如果元素的HashCode值相同,才会判断equals是否为true
如果元素的HashCode值不同,则不会判断equals。
对于判断元素是否存在,以及删除等操作,依赖的方法是
元素的hashCode和equals方法
import java.util.*;
class Person
{
private String name;
private int age;
public int hashCode() //重写父类的哈希函数
{
return name.hashCode()+age * 37;
}
public boolean equals(Object obj) //重写父类的equals方法
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return (p.name.equals(this.name) && p.age == this.age);
}
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashCodeDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
HashSet hc = new HashSet();
hc.add(new Person("lisi01",11));
hc.add(new Person("lisi02",12));
hc.add(new Person("lisi03",13));
hc.add(new Person("lisi04",14));
hc.add(new Person("lisi02",12));
//同样依赖hashCode和equals方法
sop(hc.remove(new Person("lisi01",11)));
Iterator it = hc.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName() + "::" + p.getAge());
}
}
}
14.TreeSet:可以对Set集合中的元素进行排序
底层结构是二叉树
保证元素唯一性的依据:compareTo方法return 0
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comoparable接口,覆盖compareTo方法
这种方式也称为元素的自然顺序,也称为默认顺序
注意:排序时,当主要条件相同时,一定要判断下次要条件
/*
需求:根据学生的年纪进行排序,当学生的年纪相同时,根据姓名排序
*/
import java.util.*;
class Student implements Comparable
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
public int compareTo(Object obj) //该类强制让学生具备比较性
{
if(!(obj instanceof Student))
throw new RuntimeException("比较的对象不是Student对象");
Student stu = (Student)obj;
if(this.age > stu.age)
return 1;
if(stu.age == this.age)
//排序时,当主要条件相同时,一定要判断下次要条件
//当年纪相同时,再根据姓名排序
return this.name.compareTo(stu.name);
return -1;
}
}
class TreeSetDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lisi01",20));
ts.add(new Student("lisi02",21));
ts.add(new Student("lisi02",20));
ts.add(new Student("lisi03",22));
ts.add(new Student("lisi04",23));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu = (Student)it.next();
sop(stu.getName() + "::" + stu.getAge());
}
}
}
TreeSet的第二种排序方式
当元素自身不具备比较性时,或者具备的比较性不是所需要 的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在的时候,以比较器为主
定义一个类,实现Comparator接口,覆盖compare方法
/*
需求:根据学生的年纪进行排序,当学生的年纪相同时,根据姓名排序
*/
import java.util.*;
class Student implements Comparable
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int getAge()
{
return age;
}
public String getName()
{
return name;
}
public int compareTo(Object obj) //该类强制让学生具备比较性
{
if(!(obj instanceof Student))
throw new RuntimeException("比较的对象不是Student对象");
Student stu = (Student)obj;
if(this.age > stu.age)
return 1;
if(stu.age == this.age)
return this.name.compareTo(stu.name);
return -1;
}
}
class TreeSetDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new MyCompare());
ts.add(new Student("lisi01",20));
ts.add(new Student("lisi02",21));
ts.add(new Student("lisi09",20));
ts.add(new Student("lisi007",22));
ts.add(new Student("lisi04",23));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu = (Student)it.next();
sop(stu.getName() + "::" + stu.getAge());
}
}
}
class MyCompare implements Comparator
{
//在比较器中按姓名进行排序
public int compare(Object obj1,Object obj2)
{
Student stu1 = (Student)obj1;
Student stu2 = (Student)obj2;
int num = stu1.getName().compareTo(stu2.getName());
if(num == 0)
{
return new Integer(stu1.getAge()).compareTo(new
Integer(stu2.getAge()));
}
return num;
}
}
练习
/*
练习:按照字符串长度排序
字符串本身具备比较性,但是它的比较方式不是所需要的
这是就使用比较器进行比较
*/
import java.util.*;
class TreeSetTest
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new strLenCompare());
ts.add("abc");
ts.add("d");
ts.add("esdsdcas");
ts.add("us");
ts.add("sde");
Iterator it = ts.iterator();
while(it.hasNext())
{
sop(it.next());
}
}
}
class strLenCompare implements Comparator
{
public int compare(Object o1,Object o2)
{
String s1 = (String)o1;
String s2 = (String)o2;
//注意compareTo方法返回的正数不一定是,返回的负数不一定是-1
int num = new Integer(s1.length()).compareTo(s2.length());
if(num == 0)
{
//当字符串的长度相同时,按字符串的自然顺序进行排序
return s1.compareTo(s2);
}
return num;
}
}