java中的容器类

容器的作用和概览............................................................................................................ 1

Collection接口.................................................................................................................. 2

LIST接口................................................................................................................... 2

SET接口.................................................................................................................... 3

Map接口.......................................................................................................................... 3

Iterator接口..................................................................................................................... 4

遍历集合.......................................................................................................................... 5

Collections工具类.............................................................................................................. 6

Comparable接口............................................................................................................... 6

Ø      equals和hashcode方法.............................................................................................. 7

Ø      泛型.......................................................................................................................... 9

容器的作用和概览

1.      数组总结回顾

a)        作用

是一种容器,可以在其中放置对象或基本类型数据。从而,实现使用数组管理一组对象。

b)        优势

是一种简单的线性序列,可以快速的访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。

c)        劣势

不灵活:容量事先定义好,不能随着需求的变化而扩容。

比如:我们在一个用户管理系统中,要把今天注册的所有用户取出来,那么这个用户有多少个?我们在写程序时是无法确定的。如果,你能确定那你就是神了。因此,就不能使用数组。

因此,数组远远不能满足我们的需求。我们需要一种灵活的,容量可以随时扩充的容器来装载我们的对象。这就是我们今天要学习的容器类,或者叫集合框架

 

2.      容器中的接口层次结构:

 

Collection接口

Collection 表示一组对象,它是集中,收集的意思,就是把一些数据收集起来

Collection接口的两个子接口:

         Set中的数据没有顺序,不可重复。

         List中的数据有顺序,可重复。

         Collection接口中定义的方法:

boolean  add(Object element);

boolean  remove(Object element);

boolean  contains(Object element);

int    size(); 

boolean  isEmpty();

void  clear();

Iterator  iterator();

boolean   containsAll(Collection c);

boolean  addAll(Collection c);

boolean  removeAll(Collection c);

boolean  retainAll(Collection c);    //交集

Object[] toArray();

        

LIST接口

有序的Collection。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

与 set 不同,列表通常允许重复的元素。更确切地讲,列表通常允许满足e1.equals(e2) 的元素对 e1 和e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素。

 

多了一些跟顺序有关的方法:

void add(Object element);

void add(int index, Object element);

Object  get (int index);

Object set(int index,Object element);//修改某一位置的元素          

Objectremove (int index);                      

int  indexOf (Object o);//返回某个元素的索引。如果没有该数据,返回-1

 

LinkedList:底层用双向链表实现的List。特点:查询效率低,增删效率高,线程不安全。

ArrayList:底层用数组实现的List。特点:查询效率高,增删效率低,线程不安全。

 

Vector:底层用数组实现的List,特点:线程安全。

如何选用?

线程安全用Vector。

线程不安全,查找较多用ArrayList。增加或删除元素较多用LinkedList

 

SET接口

HashSet:采用哈希算法实现的Set

HashSet的底层是用HashMap实现的,因此,查询效率高。由于采用Hashcode算法直接确定元素的内存地址,增删效率也高。

                  Set s = new HashSet();

                  s.add ("hello");

                  s.add ("world");

                  s.add (new Integer(4));

                  s.add (new Double(1.2));

                  s.add ("hello"); // 相同的元素不会被加入

                  System.out.println (s);

 

 

练习

将list、set中的方法挨个写测试。学习一下。

a)        熟悉debug。使用debug帮助我们理解学习。

b)        熟悉:typeHierarchy(类的层次关系),   call Hierarchy(方法调用关系)

 

Map接口

实现Map接口的类用来存储键(key)-值(value) 对

Map 接口的实现类有HashMap和TreeMap等。

Map类中存储的键-值对通过键来标识,所以键值不能重复。

 

HashMap: 线程不安全,效率高. 允许key或value为null

HashTable:线程安全,效率低. 不允许key或value为null

Properties[雨林木风1] : HashTable的子类,key和value都是string

 

常用的方法:

Object put(Object key, Object value);

Object get(Object key);

Object remove(Object key);

boolean containsKey(Object key);

boolean containsValue(Object value);

int size();

boolean isEmpty();

void putAll(Map t);

void clear();

 

方法测试:

        Map m1 = new HashMap();

        Map m2 = new HashMap();

        m1.put("one", new Integer(1));

        m1.put("two", new Integer(2));

        m1.put("three", new Integer(3));

 

        m2.put("A", new Integer(1));

        m2.put("B", new Integer(2));

       

        System.out.println(m1.size());

        System.out.println(m1.containsKey("one"));

        System.out.println(m2.containsValue(new Integer(1)));

        if (m1.containsKey("two")) {

            int i = ((Integer) m1.get("two")).intValue();

            System.out.println(i);

        }

        Map m3 = new HashMap(m1);

        m3.putAll(m2);

        System.out.println(m3);

 

 

 

Iterator接口[雨林木风2] 

    所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。

    Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。

    Iterator接口定义了如下方法:

        boolean hasNext();  //判断是否有元素没有被遍历

        Object next();      //返回游标当前位置的元素并将游标移动到下一个位置

        void remove();      //删除游标左面的元素,在执行完next之后该

                            //操作只能执行一次

 

遍历集合

遍历List方法1,使用普通for循环:

        for(int i=0;i<list.size();i++){

            String temp = (String)list.get(i);

            System.out.println(temp);

            //list.remove(i);     //遍历删除元素,不过不推荐这种方式!

        }

遍历List方法2,使用增强for循环(应该使用泛型定义类型!)

        for (String temp : list) {

            System.out.println(temp);

        }

遍历List方法3,使用Iterator迭代器:

        for(Iterator iter = list.iterator();iter.hasNext();){

            String temp = (String)iter.next();

            System.out.println(temp);

        }

或者:

        Iterator  iter = c.iterator();

        while(iter.hasNext()){

            Object  obj =  iter.next();

             iter.remove();      //如果要遍历删除集合中的元素,建议使用这种方式!

            System.out.println(obj);

        }

 

遍历Set方法1,:

for(String temp:set){

            System.out.println(temp);

        }

遍历Set方法2,使用iterator迭代器

        for(Iterator iter = set.iterator();iter.hasNext();){

            String temp = (String)iter.next();

            System.out.println(temp);

        }

遍历Map

//      Map<Integer, Man> maps = new HashMap<Integer, Man>();

        Set<Integer>  keySet =  maps.keySet();

        for(Integer id : keySet){

            System.out.println(maps.get(id).name);

        }

 

Collections工具类

类 java.util.Collections 提供了对Set、List、Map操作的工具方法。

void sort(List)  //对List容器内的元素排序,

                 //排序的规则是按照升序进行排序。

void shuffle(List) //对List容器内的元素进行随机排列

void reverse(List) //对List容器内的元素进行逆续排列

void fill(List, Object)  //用一个特定的对象重写整个List容器

int binarySearch(List, Object)//对于顺序的List容器,采用折半查找的                                                                            //方法查找特定对象

         List aList = new ArrayList();

         for (int i = 0; i < 5; i++)

                  aList.add("a" + i);

         System.out.println(aList);

         Collections.shuffle(aList); // 随机排列

         System.out.println(aList);

         Collections.reverse(aList); // 逆续

         System.out.println(aList);

         Collections.sort(aList); // 排序

         System.out.println(aList);

         System.out.println(Collections.binarySearch(aList, "a2"));

         Collections.fill(aList, "hello");

         System.out.println(aList);

 

 

Comparable接口

 

Ø  问题:上面的算法根据什么确定集合中对象的“大小”顺序?

Ø  所有可以“排序”的类都实现了java.lang.Comparable 接口,Comparable接口中只有一个方法

        public int compareTo(Object obj);

     该方法:

§  返回   0   表示 this == obj

§   返回正数表示 this  >  obj

§   返回负数表示 this  <  obj

Ø  实现了Comparable 接口的类通过实现 comparaTo 方法从而确定该类对象的排序方式。

 

public class TestComparable {

 

    /**

     * @param args

     */

    public static void main(String[] args) {

        List<Student> list = new ArrayList<Student>();

        Student stu1 = new Student(1,"张三",100);

        Student stu2 = new Student(2,"张四",80);

        Student stu3 = new Student(3,"张五",90);

        list.add(stu1);

        list.add(stu2);

        list.add(stu3);

        System.out.println(list);

        Collections.sort(list);

        System.out.println(list);

       

    }

 

}

 

class Student implements Comparable<Student> {

    int id;

    String name;

    int score;

   

    public Student(int id, String name, int score) {

        super();

        this.id = id;

        this.name = name;

        this.score = score;

    }

   

    public String toString(){

        return name+score;

    }

 

 

    @Override

    public int compareTo(Student o) {

        if(this.score>o.score){

            return 1;

        }else if(this.score<o.score){

            return -1;

        }else {

            return 0;

        }

    }

   

}

 

 

 

Ø  equals和hashcode方法

equals和hashcode方法:

l  Collection类对象是否相等对象在调用remove、contains 等方法时需要比较,这会涉及到对象类型的 equals 方法和hashCode方法;对于自定义的类型,需要重写equals 和 hashCode 方法以实现自定义的对象相等规则。    

注意:Java中规定,两个内容相同的对象应该具有相等的hashcode

 

什么时候需要我们重写equal,hashcode方法?

这样作的目的就是为了你的类就能够很好的与java的集合框架协同工作。如果我们能够确认我们定义的类不会和java集合类产生关系,那么我们完全没有必要在覆写equals()方法的时候覆写hashCode。

 

如下情况,可能需要我们重写equal/hashcode方法:

要将我们自定义的对象放入HashSet中处理。

         要将我们自定义的对象作为HashMap的key处理。

         放入Collection容器中的自定义对象后,可能会调用remove,contains等方法时。

 

Equal和hashcode的关系和原理:

1.      Hashcode并不是内存地址,是内存地址转换而来的。系统通过它也可以确定内存地址。

2.      hashcode方法主要用在集合框架中,目的是为了快速比较两个对象是否相等,因为集合框架中的对象很多,每个都使用equals比较效率很差。
每个对象都有一个hashcode,规定:
1、内容相同的对象hashcode肯定相等
2、内容不相同的对象hashcode可能相等也可能不相等

所以如果两个对象的hashcode不相等则两个对象的内容肯定不相等,这样就不必一个一个去比较属性的值了,从而提高对象比较的速度。

 

可以直接利用eclipse生成equal和hashcode方法,对于我们一般的程序来说已经足够了。

class Man {

    int id;

    int age;

    String name;

 

    public Man(int id, int age, String name) {

        super();

        this.age = age;

        this.name = name;

    }

 

 

    public boolean equals(Object obj) {

        if (this == obj)

            return true;

        if (obj == null)

            return false;

        if (getClass() != obj.getClass())

            return false;

        final Man other = (Man) obj;

        if (age != other.age)

            return false;

        if (id != other.id)

            return false;

        if (name == null) {

            if (other.name != null)

                return false;

        } else if (!name.equals(other.name))

            return false;

[雨林木风3]       return true;

    }

 

   

    public int hashCode() {

        final int prime = 31;

        int result = 1;

        result = prime * result + age;

        result = prime * result + id;

        result = prime * result + ((name == null) ? 0 : name.hashCode())[雨林木风4] ;

        return result;

    }

}

 

 

Ø  泛型(5.0以后增加的!!   以后大家使用容器时,建议大家使用泛型!!)

为什么需要泛型?

q  JDK1.4以前类型不明确:

n 装入集合的类型都被当作Object对待,从而失去自己的实际类型。

n 从集合中取出时往往需要转型,效率低,容易产生错误。

泛型的好处:

q  增强程序的可读性和稳定性。

泛型的使用:

        List<String> list = new ArrayList<String>();

        Set<Man> mans = new HashSet<Man>();

        Map<Integer, Man> maps = new HashMap<Integer, Man>();

        Iterator<Man> iterator = mans.iterator();

 

 

 

Ø  附录:

 

n  常见面试题:

1.      Collection 和 Collections的区别。

Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。
Collection是个java.util下的接口,它是各种集合结构的父接口。

2.      List, Set, Map是否继承自Collection接口?

List,Set是  Map不是

3.      ArrayList和Vector的区别。

一.同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的 。
二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半。

4.      HashMap和Hashtable的区别

同步性:Hashtable是线程安全的,也就是说是同步的,而HashMap是线程序不安全的,不是同步的

 


作用:

经常用于读取资源文件内容

 

所有的属性的值都相等才算相等。这个可以根据自己的实际情况进行改写。

如果只需要比较id,那么就用id 就可以了。

散列算法。

而如果只用少量的属性采样散列,极端情况会产生大量的散列冲突,如对"人"的属性中,如果用性别而不
是姓名或出生日期,那将只有两个或几个可选的hashcode值,将产生一半以上的散列冲突.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值