集合类的使用
一、集合类
1.为什么出现集合类?
在面向对象的编程思想中,都是以对象的形式对事物进行描述的,为了保证对象的生命周期,我们需要持有对象
在很多情况下,我们不知道在程序中需要创建多少个对象,这时就不能依靠定义引用对象的变量来持有每一个对象
存储对象的容器就能帮我们解决这样的问题,而集合便是这样的容器
2.数组和集合类的区别
数组和集合类都是容器,都能存储对象
3.集合类的特点
集合类可用于存储对象
集合类的长度可变
一个集合可以存储多种类型的对象
二、Collection接口
JDK1.5新定义的iterable接口为Collection的父接口
Collection接口下主要分为List集合和Set集合
1.List集合
特点:元素有序,允许有重复元素
实现List接口的一些常用集合类
a.ArrayList
底层数组实现
查找块,增删慢
线程不安全
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public String toString()
{
return name + " @ " + age;
}
}
import java.util.ArrayList;
class ArrayListTest
{
public static void main(String args[])
{
ArrayList<Person> al = new ArrayList<Person>();
al.add(new Person("张三", 20));
al.add(new Person("李四", 21));
al.add(new Person("王五", 22));
al.add(new Person("赵六", 23));
System.out.println(al.size());
for(Person p:al)
System.out.println(p);
}
}
ArrayList<Person> al = new ArrayList<Person>();
JDK1.5增加了新特性泛型,为了减少操作集合时出错的几率,集合一旦声明了泛型,便只能存储同一类型的对象
若此时没有声明泛型即:ArrayList al = new ArrayList();
则打印出来返回的对象是Ojbect的对象而非Person对象,for循环就应该这样写:
for(Object obj:al)
System.out.println(obj);
main方法前需加上注解:@SuppressWarnings("unchecked")
还有一个注解,如果想重写父类的方法,可以在前面加上@Override
这个注解明确告诉编译器是重写了父类的方法
如果没有注解,也不会有任何问题,但当你重写父类方法出现非语法错误比如拼写等这样的错误时,编译器不会报错,它会认为是一种新的方法
b.Vector
Vector和ArrayList的用法比本相同,唯一不同的是Vector支持线程同步,故线程安全,ArrayList不支持线程同步
c.LinkedList
底层链表实现
增删块,查找慢
用法与前两种集合类基本相同
List集合元素有些方法一致
add()增加元素
size()获取元素个数
List集合有序,get()获取元素
d.迭代器的使用
三种集合类均从自己的父类中继承了一个方法iterator()方法(JDK1.2版本),返回的是Iterator接口类型
就ArrayList集合类来举例:
调用迭代器的方法:al.iterator();
由于返回的是接口类型,所以定义一个Iterator类型的变量
Iterator iter = new ArrayList().iterator();
查看API中接口Iterator有哪些方法
boolean hasNext(); 如果仍有元素可以迭代,则返回 true
next(); 返回迭代的下一个元素
remove();
遍历集合中所有的元素(不用for循环)
while(iter.hasNext()) //如果仍有元素可以迭代,则返回true,否则false
{
System.out.println(iter.next());
}
注意,此时直接打印的这些都是Object类型的,虽然我们存入集合的都是Person类型
可以这样改动:Person p = (Person)iter.next();
也可以将接口声明泛型:Iterator<Person> iter = al.iterator();
ArrayList和Vector的iterator方法都是继承于父类abstractList
三种集合类中唯一例外的是Vector,它还有另外一种迭代方法elements()(JDK1.0版本)
该方法返回的是Enumeration接口类型,其实用法同iterator()方法类似,只是方法名不同而已
Enumeration接口中的方法:
boolean hasMoreElements();等同于boolean hasNext();
nextElement();等同于next();
Enumeration<Person> enumer = al.elements();
while(enumer.hasMoreElements())
{
Person p = enumer.nextElement();
System.out.println(p);
}
enum还是关键字......
e.ArrayList、Vector和LinkedList三者的区别
ArrayList、Vector和LinkedList都是Collection集合分支下List接口的实现类
相同点:元素有序,允许有重复元素,都可以调用iterator方法
ArrayList、Vector都是abstract类的子类,底层都是数组实现,都具有查找元素速度快,增删慢的特点,两者的区别就在于线程安全问题
ArrayList不支持线程同步,所以不安全。Vector线程同步,线程安全
LinkedList底层是链表实现,这样的实现查找慢,增删快。
2.Set集合
a.HashSet
底层使用哈希算法保证没有重复元素,元素无序
先调用对象的hashCode方法计算出对象的哈希值,找到位置
如果该位置没有元素,直接存
如果有,将存入的对象分别和已有的对象进行equals比较(调用对象的equals方法),如果返回为false,才能进行存储
往HashSet集合中存放的对象必须要正确地重写Object类的equals和hashCode方法
写个代码例子:
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public String toString()
{
return name + " @ " + age;
}
@Override //明确告诉编译器重写了父类的方法
public boolean equals(Object obj)
{
if(this==obj)
return true;
if(obj instanceof Person)
{
Person p = (Person)obj;
if(this.age==p.age && this.name.equals(p.name))
return true;
}
return false;
}
@Override
public int hashCode()
{
return name.hashCode()*29 + age; //调用了String类中重写的父类Object的hashCode()方法
}
}
import java.util.HashSet;
import java.util.Iterator;
class HashSetTest
{
public static void main(String args[])
{
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("张三", 20));
hs.add(new Person("李四", 21));
hs.add(new Person("王五", 22));
hs.add(new Person("赵六", 23));
System.out.println(hs.size());
Iterator<Person> iter = hs.iterator();
while(iter.hasNext())
{
Person p = iter.next();
System.out.println(p);
}
}
}
b.TreeSet
TreeSet集合是接口Set的实现类,通过二叉树算法保证无重复元素,实现了元素的排序
(1).按照元素的自然顺序进行排序,这时需要对象实现Comparable接口的compareTo方法
public class Student implements Comparable
{
private String name;
private int age;
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public String toString()
{
return name + " @ " + age;
}
//先按照age顺序排,在按照字母顺序排
public int compareTo(Object obj)
{
Student stu = (Student)obj;
int num = this.age - stu.age;
if(num!=0)
return num;
return this.name.compareTo(stu.name);
}
}
import java.util.TreeSet;
import java.util.Iterator;
public class TreeSetTest
{
public static void main(String args[])
{
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("zhangsan", 20));
ts.add(new Student("lisi", 21));
ts.add(new Student("wangwu", 22));
ts.add(new Student("zhaoliu", 23));
ts.add(new Student("qianqi", 23));
System.out.println(ts.size());
Iterator<Student> iter = ts.iterator();
while(iter.hasNext())
{
Student stu = iter.next();
System.out.println(stu);
}
}
}
(2).在构造TreeSet对象时,扔进一个比较器,所谓比较器就是Comparator接口的子类,需要实现compare方法
public class Student
{
private String name;
private int age;
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
@Override
public String toString()
{
return name + " @ " + age;
}
}
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
public class TreeSetTest
{
public static void main(String args[])
{
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>(){
public int compare(Student stu1, Student stu2)
{
int num1 = stu1.getAge() - stu2.getAge();
int num2 = stu1.getName().compareTo(stu2.getName());
if(num2!=0)
return num2;
return num1;
}
});
ts.add(new Student("zhangsan", 20));
ts.add(new Student("lisi", 21));
ts.add(new Student("wangwu", 22));
ts.add(new Student("zhaoliu", 23));
ts.add(new Student("qianqi", 23));
System.out.println(ts.size());
Iterator<Student> iter = ts.iterator();
while(iter.hasNext())
{
Student stu = iter.next();
System.out.println(stu);
}
}
}
运用了组合设计模式,传入了Comparator接口的子类,然后实现其中的compare方法,接口Comparator的equals方法没有实现,是因为子类自动继承了Object父类的equals方法
在创建Comparator接口子类的时候也要注明泛型:new Comparator<Student>(){...};
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zsx923/archive/2009/11/21/4849086.aspx