集合类的使用

集合类的使用

一、集合类

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值