初学者学Java(十八)

                    可变的数组-----集合类之Set接口

        在前面两篇我讲了List接口和他的两个实现类,在这一篇我和大家一起探讨一下Set接口和他的实现类。 

        我觉的在集合的所有接口里,只有Set接口与数学上的集合的概念是最接近的,因为Set结合包含了数学上集合的三大特性中的两个:

       1.不包含重复元素。

       2.元素之间没有顺序。

       这也是Set和List的区别。这个接口也有两个实现类:HashSet和TreeSet。

                                                  HashSet类

         这个类的特点是元素的顺序是不确定的,而且不能添加相同的元素。那他是怎么判断两个元素是否相同呢?他需要满足下面这个关系式:

                                                                e==null ? e2==null : e.equals(e2)

         通过上面这个表达式我们可以看出,就算是NULL,HashSet中也只能存在一个。对于非空元素,只要集合中没有能和他equals()返回true的,就可以加入。

         在这个类中,并没有重新equals()方法,所以他是继承的Object类中的方法,在这里我们来看一下这个方法的源码:

public boolean equals(Object obj) {

        return (this == obj);

}

         大家都知道两个对象是否“==”,看的是toString()方法,我们再看一下他的源码:

public String toString()

{

        return      getClass().getName()+"@"+Integer.toHexString(hashCode());

}

在这里大家就可以看出他先是比较了这两个类是否是同一个类,然后再比较对象地址的哈希码表示是否相同。

这里提到了方法hashCode():返回该对象的哈希码值。

他有一下这么几个规定:

     1.在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

     2.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

     3.如果根据 equals(java.lang.Object)方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

        这段文字摘自帮助文档中,主要表达的意思是对于不同的对象会产生不同的哈希码值。

        所以除非类中重写了equals()或hashCode()(String类重写了该方法),否则同类两个对象的比较是比较内存地址是否相同。

        当使用 HashSet 时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code 值是否与增加的对象的 hashcode 值一致;如果不一致,直接加进去;如果一致,再进行 equals 方法的比较,equals 方法如果返回 true,表示对象已经加进去了,就不会再增加新的对象,否则加进去。

关于这个类的几个方法:

        构造方法:publicHashSet();构造一个新的空set,其底层 HashMap 实例的默认初始容量                                                                是16;

        添加元素:public boolean add(E e):如果此 set 中尚未包含指定元素,则添加指定元素。

        删除元素:public boolean remove(Object o):如果指定元素存在于此set 中,则将其移除。

        迭代器:public Iterator<E> iterator():返回对此set 中元素进行迭代的迭代器。

        我们来说一下最后一个方法,因为Set集合中的元素是无序的,所以我们不能像数组一样用索引一样来调用,也不能像链表一样用引用来调用。为了解决调用的问题,我们引入了迭代器的概念,并非只有HashSet类中有迭代器,每个集合中都有迭代器(包括List接口)。

迭代器有以下几个方法:

       boolean hasNext():如果仍有元素可以迭代,则返回true。(换句话说,如果next 返回了元素而不是抛出异常,则返回 true)。也就是说,如果还有下一个元素就返回true。

        E next():返回下一个元素。

          我们写一个程序来说明一下:

import java.util.HashSet;

import java.util.Iterator;

 

public class HashSetTest {

    public static void main(String[]args) {

        HashSet setOne = new HashSet();

        setOne.add("a");

        for(Iterator iter =setOne.iterator();iter.hasNext();)

        {

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

        }

 

    }

}

这里表现了迭代器最常见的用法,也称作遍历集合。下面我们来讲一下:TreeSet

                                                               TreeSet

       TreeSet类不仅实现了Set接口,也实现了SortedSet接口,因此TreeSet类在遍历集合的时候可以按自然顺序排序,也可以按自定义顺序来排序(String类是按字典的顺序排序的)。

而如何来定义排序的顺序呢?

        这就要说到另一个接口了:Comparator.

这个接口定义了比较器,一般在使用TreeSet时我们会写一个这个接口的实现类,来完成我们需要的功能,例如我们要为学生的成绩按从高到低排序,可以这样写:

import java.util.*;

public class TreeSetTest {

    public static void main(String[]args) {

        TreeSet setOne = new TreeSet(new ComparatorOne());

        setOne.add(new Person(90));

        setOne.add(new Person(100));

        setOne.add(new Person(80));

        for(Iterator ite =setOne.iterator();ite.hasNext();)

        {

            System.out.println(((Person)ite.next()).getSocer());

        }

    }

}

class Person

{

    private int socer;

 

    public int getSocer() {

        return socer;

    }

    public void setSocer(int socer) {

        this.socer = socer;

    }

    public Person(int socer)

    {

        this.socer = socer;

    }

}

class ComparatorOne implements Comparator

{

    public int compare(Object o1, Object o2) {

        Person personOne = (Person)o1;

        Person personTwo = (Person)o2;

        returnpersonTwo.getSocer()-personOne.getSocer();

    }

}

     因为我们想要让成绩高的排在前面,所以我们返回

              personTwo.getSocer()-personOne.getSocer();

     如果第一个同学的成绩高于第二个就返回负数,而在TreeSet中返回负数的排在前面。

     有关TreeSet的构造方法常用的有两个:

             1.public TreeSet();

             2.publicTreeSet(Comparator  comparator)

我们在实际应用中一般用第二个,因为我们需要自己定义比较方法。

关于Set接口我就说这么多吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值